├── .gitignore ├── README.md ├── android ├── AndroidManifest.xml ├── assets │ ├── badlogic.jpg │ └── data │ │ ├── bg.png │ │ ├── cat_0.png │ │ ├── cat_1.png │ │ ├── cat_2.png │ │ ├── cat_3.png │ │ ├── play.png │ │ ├── start.png │ │ └── takepictures.png ├── build.gradle ├── ic_launcher-web.png ├── proguard-project.txt ├── project.properties ├── res │ ├── drawable-hdpi │ │ └── ic_launcher.png │ ├── drawable-mdpi │ │ └── ic_launcher.png │ ├── drawable-xhdpi │ │ └── ic_launcher.png │ ├── drawable-xxhdpi │ │ └── ic_launcher.png │ └── values │ │ ├── strings.xml │ │ └── styles.xml └── src │ └── pri │ └── weiqiang │ └── camera │ ├── AndroidDeviceCameraController.java │ ├── AndroidLauncher.java │ └── CameraSurface.java ├── build.gradle ├── core ├── build.gradle └── src │ └── pri │ └── weiqiang │ └── camera │ ├── AndroidCamera.java │ └── DeviceCameraControl.java ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── old_version ├── README.md ├── android │ └── src │ │ └── com │ │ └── mygdx │ │ └── game0606 │ │ └── android │ │ ├── AndroidDeviceCameraController.java │ │ ├── AndroidLauncher.java │ │ └── CameraSurface.java ├── core │ └── src │ │ ├── MyGdxGame0606.gwt.xml │ │ └── com │ │ └── mygdx │ │ └── game0606 │ │ ├── Constant.java │ │ ├── DeviceCameraControl.java │ │ ├── MyGdxGame0606.java │ │ ├── actor │ │ └── FirstActor.java │ │ └── util │ │ └── GetUrlImg.java └── ver_2016.7.21.11.18 │ ├── Android │ └── src │ │ └── com │ │ └── mygdx │ │ └── game0606 │ │ └── android │ │ ├── AndroidDeviceCameraController.java │ │ ├── AndroidLauncher.java │ │ └── CameraSurface.java │ ├── README.md │ └── core │ └── src │ ├── MyGdxGame0606.gwt.xml │ └── com │ └── mygdx │ └── game0606 │ ├── Constant.java │ ├── DeviceCameraControl.java │ ├── MyGdxGame0606.java │ ├── actor │ └── FirstActor.java │ └── util │ └── GetUrlImg.java ├── readme_img ├── 1.jpg ├── 2.jpg ├── 3.png └── 4.jpg └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | ## Java 2 | 3 | *.class 4 | *.war 5 | *.ear 6 | hs_err_pid* 7 | 8 | ## Robovm 9 | robovm-build/ 10 | 11 | ## GWT 12 | war/ 13 | html/war/gwt_bree/ 14 | html/gwt-unitCache/ 15 | .apt_generated/ 16 | html/war/WEB-INF/deploy/ 17 | html/war/WEB-INF/classes/ 18 | .gwt/ 19 | gwt-unitCache/ 20 | www-test/ 21 | .gwt-tmp/ 22 | 23 | ## Android Studio and Intellij and Android in general 24 | android/libs/armeabi/ 25 | android/libs/armeabi-v7a/ 26 | android/libs/arm64-v8a/ 27 | android/libs/x86/ 28 | android/libs/x86_64/ 29 | android/gen/ 30 | .idea/ 31 | *.ipr 32 | *.iws 33 | *.iml 34 | out/ 35 | com_crashlytics_export_strings.xml 36 | 37 | ## Eclipse 38 | .classpath 39 | .project 40 | .metadata 41 | **/bin/ 42 | tmp/ 43 | *.tmp 44 | *.bak 45 | *.swp 46 | *~.nib 47 | local.properties 48 | .settings/ 49 | .loadpath 50 | .externalToolBuilders/ 51 | *.launch 52 | 53 | ## NetBeans 54 | **/nbproject/private/ 55 | build/ 56 | nbbuild/ 57 | dist/ 58 | nbdist/ 59 | nbactions.xml 60 | nb-configuration.xml 61 | 62 | ## Gradle 63 | 64 | .gradle 65 | gradle-app.setting 66 | build/ 67 | 68 | ## OS Specific 69 | .DS_Store 70 | Thumbs.db 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 完整代码已上传github,https://github.com/54wall/LibgdxAndroidCamera 2 | 3 | ## 开发背景 ## 4 | 5 | 简单介绍下本文主要介绍了下如何libGDX调用android摄像头的步骤,内容非原创。通过在Libgdx中调用摄像头,可以实现伪AR游戏:一个是抓幽灵的游戏ChaseWhisplyProject,来自 6 | ![ChaseWhisplyProject](https://github.com/54wall/LibgdxAndroidCamera/blob/master/readme_img/1.jpg) 7 | 8 | 另外一个beyondar,来自 9 | 10 | ![beyondar](https://github.com/54wall/LibgdxAndroidCamera/blob/master/readme_img/2.jpg) 11 | 12 | 当然,上边两个全部在Android内实现的,而非在libgdx中实现,感谢Github,在libGDX的介绍中,有达人分享了他使用libGDX调用android摄像头的实例,他在libGDX中调用摄像头的目的简单来说就是AR,使用者可以通过APP看到设备背后的路面,或者和真实世界有交互,就像PokemonGO一样,当然全部的这些也需要算法支持。但是时间是2013年,我拷贝下来,进行了微调,发现是可以实现的,鉴于目前网络上还真没有许多的实例说明如何在LibGDX中调用android摄像头,我搜索libgdx camera 大部分给我的结果都是libgdx中的镜头,就是跟随演员的镜头,而不是设备摄像头,这里也对这个实例进行一个记录和补充,以及简单的实现。 13 | 14 | wiki地址:[https://github.com/libgdx/libgdx/wiki/Integrating-libgdx-and-the-device-camera](https://github.com/libgdx/libgdx/wiki/Integrating-libgdx-and-the-device-camera) 15 | 16 | 下面我也是基于这篇文章进行翻译,顺序当然有所改变,还有原代码中有包含一个类似初始页面的SplashActivity的我没有实现,目前还没有去了解libGDX的三维编程,代码的源码已上传至GitHub,再好的文字也比不上源码。 17 | 完整代码已上传github,https://github.com/54wall/LibgdxAndroidCamera 18 | **libGDX中到底是如何实现调用摄像头** 19 | 20 | 很简单,就是在一个透明的画布上绘制libGDX的舞台演员,在画布的后边放置摄像头的预览画面。而文章主要解决的问题就是如何显示摄像头预览画面,和如何调用摄像头。 21 | 22 | **如何显示摄像头预览画面** 23 | 24 | 我们知道,libGDX的代码主要全部在core项目中,其他各个平台的代码都是经过一个简单的代码启动启动然后,剩下的就去调用core项目中的代码,首先在libGDX初始化时,要进行一定的设置,才能让摄像头的预览画面显示在libGDX框架生成的app中,进入android项目组,修改AndroidLauncher.class代码如下 25 | 26 | ```java 27 | AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration(); 28 | cfg.r = 8; 29 | cfg.g = 8; 30 | cfg.b = 8; 31 | cfg.a = 8; 32 | DeviceCameraControl cameraControl = new AndroidDeviceCameraController(this); 33 | initialize(new MyGdxGame0606(cameraControl), cfg); 34 | ``` 35 | 36 | 你可以点击进入AndroidApplicationConfiguration去看看r,g,b,a原来数值如下 37 | 38 | ```java 39 | /** number of bits per color channel **/ 40 | public int r = 5, g = 6, b = 5, a = 0; 41 | ``` 42 | 43 | rgba的具体值指的是每种颜色的比特位数,这里改为8位,大概的意思就是每种颜色深度为8位,也就是2的8次幂,也就是256,和photoshop中意义一样。这么设置的原因是为了libGDX中的画布的后边能够正常的显示android的摄像头,不然颜色和在android上调用摄像头有出入,色彩不会同样的丰富。 44 | 45 | 同样在AndroidLauncher.class中,将OpenGL surface 模式设置成TRANSLUCENT 46 | 47 | 48 | ```java 49 | if (graphics.getView() instanceof SurfaceView) { 50 | SurfaceView glView = (SurfaceView) graphics.getView(); 51 | // force alpha channel - I'm not sure we need this as the GL surface 52 | // is already using alpha channel 53 | glView.getHolder().setFormat(PixelFormat.TRANSLUCENT); 54 | } 55 | ``` 56 | 57 | 然后是,在AndroidLauncher.class新建一个post方法,用来帮助唤起一些异步线程 58 | 59 | ```java 60 | public void post(Runnable r) { 61 | handler.post(r); 62 | } 63 | ``` 64 | 65 | 以上就是AndroidLauncher.class所要完成的全部内容。 66 | **如何让屏幕透明** 67 | 68 | 很简单,在core项目中MyGdxGame0606.class主类中的render()渲染方法中,要注意使用glClearColor()清屏时,参数的选择必须全部是0,这样相机预览的画面才会显示在render画面的后边 69 | 70 | ```java 71 | Gdx.gl20.glClearColor(0f, 0.0f, 0.0f, 0.0f); 72 | ``` 73 | 74 | **清屏准备完毕,现在就是要调用android摄像头的时候到了** 75 | 76 | 首先了解一下,把大象装冰箱中总共分几步?对于调用android摄像头的步骤则可以分如下几部?Android相机有特别的工作顺序必须遵守,通过application的callbacks回调函数能管理相机的状态,机器的工作状态将由AndroidDeviceCameraController.class进行管理(desktop没有实现,Android已实现)。 77 | 相机的工作状态一次是 Ready -> Preview -> autoFocusing -> ShutterCalled -> Raw PictureData -> Postview PictureData -> Jpeg PictureData -> Ready (可以做一个表格) 78 | 本实例代码实现的顺序也可以概括为 Ready -> Preview -> autoFocusing -> Jpeg PictureData -> Ready 79 | **新建AndroidDeviceCameraController** 80 | 81 | 在core项目中,新建一个DeviceCameraController类,而为了配合core中DeviceCameraControl,在android项目中,新建一个AndroidDeviceCameraController 类,来控制设备的摄像头,它要继承DeviceCameraControl,同时还要实现Camera.PictureCallback:(android.hardware.Camera.PictureCallback)Camera.AutoFocusCallback(android.hardware.Camera.AutoFocusCallback),共计三个接口,来实现android摄像头从准备到拍摄的过程。 82 | 83 | ```java 84 | public class AndroidDeviceCameraController implements DeviceCameraControl, Camera.PictureCallback, Camera.AutoFocusCallback { 85 | } 86 | ``` 87 | AndroidDeviceCameraController 新建后,逐步实现摄像头该有的各个功能。 88 | **1.准备显示预览信息的CameraSurface** 89 | 90 | 我们产生一个CameraSurface类来负责管理摄像头和它收集的图像,这里我和android摄像相关的代码一致 91 | 92 | ```java 93 | public class CameraSurface extends SurfaceView implements SurfaceHolder.Callback { 94 | private Camera camera; 95 | public CameraSurface( Context context ) { 96 | super( context ); 97 | // We're implementing the Callback interface and want to get notified 98 | // about certain surface events. 99 | getHolder().addCallback( this ); 100 | // We're changing the surface to a PUSH surface, meaning we're receiving 101 | // all buffer data from another component - the camera, in this case. 102 | getHolder().setType( SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS ); 103 | } 104 | public void surfaceCreated( SurfaceHolder holder ) { 105 | // Once the surface is created, simply open a handle to the camera hardware. 106 | camera = Camera.open(); 107 | } 108 | public void surfaceChanged( SurfaceHolder holder, int format, int width, int height ) { 109 | // This method is called when the surface changes, e.g. when it's size is set. 110 | // We use the opportunity to initialize the camera preview display dimensions. 111 | Camera.Parameters p = camera.getParameters(); 112 | p.setPreviewSize( width, height ); 113 | camera.setParameters( p ); 114 | // We also assign the preview display to this surface... 115 | try { 116 | camera.setPreviewDisplay( holder ); 117 | } catch( IOException e ) { 118 | e.printStackTrace(); 119 | } 120 | } 121 | public void surfaceDestroyed( SurfaceHolder holder ) { 122 | // Once the surface gets destroyed, we stop the preview mode and release 123 | // the whole camera since we no longer need it. 124 | camera.stopPreview(); 125 | camera.release(); 126 | camera = null; 127 | } 128 | public Camera getCamera() { 129 | return camera; 130 | } 131 | } 132 | ``` 133 | 134 | **2.在android项目中增加相机预览视图** 135 | 136 | 在android项目的AndroidDeviceController类,使用activity.addContentView,直接将cameraSurface显示在android设备的屏幕上 137 | 138 | ```java 139 | @Override 140 | public void prepareCamera() { 141 | if (cameraSurface == null) { 142 | cameraSurface = new CameraSurface(activity); 143 | } 144 | activity.addContentView( cameraSurface, new LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT ) ); 145 | } 146 | ``` 147 | 148 | ```java 149 | @Override 150 | public synchronized void prepareCamera() { 151 | if (cameraSurface == null) { 152 | cameraSurface = new CameraSurface(activity); 153 | } 154 | FrameLayout.LayoutParams params = new FrameLayout.LayoutParams (680,680); 155 | params.rightMargin=150;//可以通过设置rightMargin控制组件的实际位置 156 | params.leftMargin=200;//可以通过设置rightMargin控制组件的实际位置 157 | params.topMargin=100; 158 | activity.addContentView(cameraSurface, params); 159 | 160 | 161 | } 162 | ``` 163 | 164 | prepareCamera方法应该在libgdx渲染过程中异步调用 165 | 166 | ```java 167 | @Override 168 | public void prepareCameraAsync() { 169 | Runnable r = new Runnable() { 170 | public void run() { 171 | prepareCamera(); 172 | } 173 | }; 174 | activity.post(r); 175 | } 176 | 177 | @Override 178 | public void prepareCameraAsync() { 179 | Runnable r = new Runnable() { 180 | public void run() { 181 | prepareCamera(); 182 | } 183 | }; 184 | activity.post(r); 185 | } 186 | ``` 187 | 188 | 当CameraSurface和camera 对象准备好了的时候(通过检测cameraSurface!=null && cameraSurface.getCamera() != null),就可以让相机由准备状态进入预览模式 189 | 190 | ```java 191 | @Override 192 | public boolean isReady() { 193 | if (cameraSurface!=null && cameraSurface.getCamera() != null) { 194 | return true; 195 | } 196 | return false; 197 | } 198 | ``` 199 | 200 | ```java 201 | @Override 202 | public boolean isReady() { 203 | if (cameraSurface != null && cameraSurface.getCamera() != null) { 204 | return true; 205 | } 206 | return false; 207 | } 208 | ``` 209 | 210 | 异步调用开启预览 211 | 212 | ```java 213 | @Override 214 | public synchronized void startPreviewAsync() { 215 | Runnable r = new Runnable() { 216 | public void run() { 217 | startPreview(); 218 | } 219 | }; 220 | activity.post(r); 221 | } 222 | @Override 223 | public synchronized void startPreview() { 224 | // ...and start previewing. From now on, the camera keeps pushing preview 225 | // images to the surface. 226 | if (cameraSurface != null && cameraSurface.getCamera() != null) { 227 | cameraSurface.getCamera().startPreview(); 228 | } 229 | } 230 | ``` 231 | 232 | **3.由预览模式进行拍照** 233 | 234 | 拍照前还要AndroidDeviceCameraController类设置下相机合适的参数 235 | 236 | 237 | ```java 238 | public void setCameraParametersForPicture(Camera camera) { 239 | // Before we take the picture - we make sure all camera parameters are as we like them 240 | // Use max resolution and auto focus 241 | Camera.Parameters p = camera.getParameters(); 242 | List supportedSizes = p.getSupportedPictureSizes(); 243 | int maxSupportedWidth = -1; 244 | int maxSupportedHeight = -1; 245 | for (Camera.Size size : supportedSizes) { 246 | if (size.width > maxSupportedWidth) { 247 | maxSupportedWidth = size.width; 248 | maxSupportedHeight = size.height; 249 | } 250 | } 251 | p.setPictureSize(maxSupportedWidth, maxSupportedHeight); 252 | p.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); 253 | camera.setParameters( p ); 254 | } 255 | ``` 256 | 257 | 接下来,我们将通过设置相机的参数,设置聚焦为自动模式, 258 | 259 | ```java 260 | @Override 261 | public synchronized void takePicture() { 262 | // the user request to take a picture - start the process by requesting focus 263 | setCameraParametersForPicture(cameraSurface.getCamera()); 264 | cameraSurface.getCamera().autoFocus(this); 265 | } 266 | ``` 267 | 268 | 当聚焦完成后,我们就要拍照了,仅仅实现JPG回调实现 269 | 270 | 271 | ```java 272 | @Override 273 | public synchronized void onAutoFocus(boolean success, Camera camera) { 274 | // Focus process finished, we now have focus (or not) 275 | if (success) { 276 | if (camera != null) { 277 | camera.stopPreview(); 278 | // We now have focus take the actual picture 279 | camera.takePicture(null, null, null, this); 280 | } 281 | } 282 | } 283 | @Override 284 | public synchronized void onPictureTaken(byte[] pictureData, Camera camera) { 285 | this.pictureData = pictureData; 286 | } 287 | 288 | @Override 289 | public synchronized void onAutoFocus(boolean success, Camera camera) { 290 | // Focus process finished, we now have focus (or not) 291 | if (success) { 292 | if (camera != null) { 293 | camera.stopPreview(); 294 | /*增加三个回调函数shutterCallback, rawPictureCallback, jpegPictureCallback后,可以进行拍照,并且成功保存*/ 295 | // We now have focus take the actual picture 296 | camera.takePicture(shutterCallback, rawPictureCallback, jpegPictureCallback);//54wall 297 | camera.startPreview(); 298 | 299 | } 300 | } 301 | } 302 | 303 | @Override 304 | public synchronized void onPictureTaken(byte[] pictureData, Camera camera) { 305 | // We got the picture data - keep it 306 | this.pictureData = pictureData; 307 | } 308 | 309 | ShutterCallback shutterCallback = new ShutterCallback() { 310 | @Override 311 | public void onShutter() { 312 | } 313 | }; 314 | 315 | PictureCallback rawPictureCallback = new PictureCallback() { 316 | @Override 317 | public void onPictureTaken(byte[] arg0, Camera arg1) { 318 | 319 | } 320 | }; 321 | 322 | PictureCallback jpegPictureCallback = new PictureCallback() { 323 | @Override 324 | public void onPictureTaken(byte[] arg0, Camera arg1) { 325 | /*可以在Android项目中中生成图片*/ 326 | // String fileName = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) 327 | // .toString() 328 | // + File.separator 329 | // + "PicTest_" + System.currentTimeMillis() + ".jpg"; 330 | // File file = new File(fileName); 331 | // if (!file.getParentFile().exists()) { 332 | // file.getParentFile().mkdir(); 333 | // } 334 | // 335 | // try { 336 | // BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file)); 337 | // bos.write(arg0); 338 | // bos.flush(); 339 | // bos.close(); 340 | // 341 | // } catch (Exception e) { 342 | // 343 | // } 344 | pictureData=arg0; 345 | 346 | }; 347 | }; 348 | ``` 349 | 以上就是拍照的具体步骤,之后照片完成后,需要将图像数据进行保存到存储器上 350 | 拍照的具体功能实现了,为了在libgdx中能够看到摄像头,当然需要在实现ApplicationListener的主类的render()进行设置了,我这里设置了三个按钮,功能分别是开启相机,进行拍摄,和一个控制人物移动的按钮(算是证明是在libgdx框架内部的)。 351 | 原代码时触控进入相机预览,松开则进行拍照,我开始还没太理解,render中因为涉及到相机的功能切换,所以在libgdx主类中定义了相机的这几种状态 352 | ```java 353 | public enum Mode { 354 | normal, prepare, preview, takePicture, waitForPictureReady, 355 | }, 356 | ``` 357 | render()中的代码非常长,不过就是在相机的各个状态中切换,具体代码如下: 358 | ```java 359 | @Override 360 | public void render() { 361 | // Gdx.gl20.glClearColor(0.0f, 0f, 0.0f, 0.0f);//黑 362 | // Gdx.gl.glClearColor(1, 1, 1, 1);//背景为白色 363 | Gdx.gl.glClearColor(0.57f, 0.40f, 0.55f, 1.0f);// 紫色 364 | Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);// 清屏 365 | render_preview(); 366 | 367 | } 368 | 369 | 370 | public void render_preview() { 371 | /* 我已经将preview变为takePicture状态移动到click中,实现先预览再拍照,这样便于理解相机的运行步骤 */ 372 | Gdx.gl20.glHint(GL20.GL_GENERATE_MIPMAP_HINT, GL20.GL_NICEST); 373 | if (mode == Mode.takePicture) { 374 | Gdx.gl20.glClearColor(0f, 0.0f, 0.0f, 0.0f); 375 | if (deviceCameraControl != null) { 376 | deviceCameraControl.takePicture(); 377 | } 378 | mode = Mode.waitForPictureReady; 379 | } else if (mode == Mode.waitForPictureReady) { 380 | Gdx.gl20.glClearColor(0.0f, 0f, 0.0f, 0.0f); 381 | } else if (mode == Mode.prepare) { 382 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0f, 0.6f); 383 | if (deviceCameraControl != null) { 384 | if (deviceCameraControl.isReady()) { 385 | deviceCameraControl.startPreviewAsync(); 386 | mode = Mode.preview; 387 | } 388 | } 389 | } else if (mode == Mode.preview) { 390 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0.0f, 0f); 391 | } else { 392 | /* mode = normal */ 393 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0.6f, 1.0f); 394 | 395 | } 396 | Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT); 397 | /* 下边放到texture.bind();时效果一致 */ 398 | batch.begin(); 399 | stage.act(); // 更新舞台逻辑 400 | batch.draw(texture, 0, 0, 3f*texture.getWidth(), 3f*texture.getHeight()); 401 | Gdx.app.log("", String.valueOf(texture.getWidth())); 402 | //先绘制的就先出现,所以演员在texture上边,而不是被覆盖 403 | //batch.draw(actorTexture, firstActor.getX(), firstActor.getY());//原大小 404 | batch.draw(actorTexture, firstActor.getX(), firstActor.getY(),4*actorTexture.getWidth(),4*actorTexture.getWidth());//可控制绘制图像大小 405 | button_move.draw(batch, 1.0f); 406 | stage.draw();// 绘制舞台 407 | batch.end(); 408 | Gdx.gl20.glEnable(GL20.GL_DEPTH_TEST); 409 | Gdx.gl20.glEnable(GL20.GL_TEXTURE); 410 | Gdx.gl20.glEnable(GL20.GL_TEXTURE_2D); 411 | // Gdx.gl20.glEnable(GL20.GL_LINE_SMOOTH);//old 412 | Gdx.gl20.glEnable(GL20.GL_LINE_LOOP);//54wall 413 | Gdx.gl20.glDepthFunc(GL20.GL_LEQUAL); 414 | Gdx.gl20.glClearDepthf(1.0F); 415 | camera.update(true); 416 | // camera.apply(Gdx.gl20);//old 417 | texture.bind(); 418 | 419 | if (mode == Mode.waitForPictureReady) { 420 | /*注意deviceCameraControl.getPictureData()得到的是byte[],可见整体思路就是, 421 | *将Android摄像头得到byte[],然后将byte[]转换为Pixmap,最后将pixmap存为jpg,这样不适用Android端图片保存模式, 422 | *byte[]----Pixmap----jpg 423 | */ 424 | if (deviceCameraControl.getPictureData() != null) { 425 | // camera picture was actually takentake Gdx Screenshot 426 | Pixmap screenshotPixmap = getScreenshot(0, 0, 427 | Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true); 428 | Pixmap cameraPixmap = new Pixmap( 429 | deviceCameraControl.getPictureData(), 0, 430 | deviceCameraControl.getPictureData().length); 431 | merge2Pixmaps(cameraPixmap, screenshotPixmap); 432 | // we could call PixmapIO.writePNG(pngfile, cameraPixmap); 433 | //仅保存screenshot,对同一时间的图片进行保存然后进行比较 434 | Pixmap screenshotPixmap_test = getScreenshot(0, 0, 435 | Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true); 436 | FileHandle jpgfile_screenshot = Gdx.files 437 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date 438 | + "_screenshot.jpg"); 439 | deviceCameraControl.saveAsJpeg(jpgfile_screenshot, 440 | screenshotPixmap_test); 441 | //仅保存cameraPixma,对同一时间的图片进行保存然后进行比较 442 | Pixmap cameraPixmap_test = new Pixmap( 443 | deviceCameraControl.getPictureData(), 0, 444 | deviceCameraControl.getPictureData().length); 445 | FileHandle jpgfile_cameraPixmap = Gdx.files 446 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date 447 | + "_camera.jpg"); 448 | deviceCameraControl.saveAsJpeg(jpgfile_cameraPixmap, 449 | cameraPixmap_test); 450 | //保存混合之后的相片 451 | FileHandle jpgfile = Gdx.files 452 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date 453 | + ".jpg"); 454 | Gdx.app.log("FileHandle", date); 455 | time_1 = System.currentTimeMillis(); 456 | deviceCameraControl.saveAsJpeg(jpgfile, cameraPixmap); 457 | time_2 = System.currentTimeMillis(); 458 | //可以得到35830ms=35s,所以非常忙,导致Mode非常缓慢的回到Mode.normal 459 | Gdx.app.log("cost", String.valueOf(time_2 - time_1)); 460 | deviceCameraControl.stopPreviewAsync(); 461 | //保存文件后,mode回到normal继续render循环,所以中间停顿和logcat长时间未动的其实是卡住了Org 462 | mode = Mode.normal; 463 | 464 | } 465 | } 466 | // 这个log将会一直出现,所以render其实是一直在执行 467 | // Gdx.app.log("mode", String.valueOf(i_render++)); 468 | } 469 | ``` 470 | **如何实现libgdx端的截图** 471 | 472 | 因为AndroidDeviceCameraController 实现两个接口: Camera.PictureCallback,所以可以直接调用,而deviceCameraControl.getPictureData()的byte[]数据则来自AndroidDeviceCameraController,如下 473 | ```java 474 | @Override 475 | public synchronized byte[] getPictureData() { 476 | // Give to picture data to whom ever requested it 477 | return pictureData; 478 | } 479 | if (deviceCameraControl.getPictureData() != null) { // camera picture was actually taken 480 | Pixmap cameraPixmap = new Pixmap(deviceCameraControl.getPictureData(), 0, deviceCameraControl.getPictureData().length); 481 | } 482 | ``` 483 | 484 | 下面是截图的具体操作过程是保存为pixmap,libgdx中保存格式都是pixmap,而非android中的bitmap 485 | 486 | ```java 487 | public Pixmap getScreenshot(int x, int y, int w, int h, boolean flipY) { 488 | Gdx.gl.glPixelStorei(GL10.GL_PACK_ALIGNMENT, 1); 489 | final Pixmap pixmap = new Pixmap(w, h, Format.RGBA8888); 490 | ByteBuffer pixels = pixmap.getPixels(); 491 | Gdx.gl.glReadPixels(x, y, w, h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, pixels); 492 | final int numBytes = w * h * 4; 493 | byte[] lines = new byte[numBytes]; 494 | if (flipY) { 495 | final int numBytesPerLine = w * 4; 496 | for (int i = 0; i < h; i++) { 497 | pixels.position((h - i - 1) * numBytesPerLine); 498 | pixels.get(lines, i * numBytesPerLine, numBytesPerLine); 499 | } 500 | pixels.clear(); 501 | pixels.put(lines); 502 | } else { 503 | pixels.clear(); 504 | pixels.get(lines); 505 | } 506 | return pixmap; 507 | } 508 | ``` 509 | 510 | 接下来的操作都是需要消耗大量时间和CPU资源的,首先不应放到UI线程中,应该新开线程去执行,并且最好加一个进度条,在代码示例中,我们并没有那么做,所以屏幕在这个过程中会出现卡死的状况。我这里则直接保存了三分文件,分别是截图,android摄像头的拍摄相片,还有二者混合之后的图片,代码如下 511 | 512 | 513 | ```java 514 | /* 仅保存screenshot,对同一时间的图片进行保存然后进行比较 */ 515 | Pixmap screenshotPixmap_test = getScreenshot(0, 0, 516 | Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true); 517 | FileHandle jpgfile_screenshot = Gdx.files 518 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date 519 | + "_screenshot.jpg"); 520 | deviceCameraControl.saveAsJpeg(jpgfile_screenshot, 521 | screenshotPixmap_test); 522 | /* 仅保存cameraPixma,对同一时间的图片进行保存然后进行比较 */ 523 | Pixmap cameraPixmap_test = new Pixmap( 524 | deviceCameraControl.getPictureData(), 0, 525 | deviceCameraControl.getPictureData().length); 526 | FileHandle jpgfile_cameraPixmap = Gdx.files 527 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date 528 | + "_camera.jpg"); 529 | deviceCameraControl.saveAsJpeg(jpgfile_cameraPixmap, 530 | cameraPixmap_test); 531 | /* 保存混合之后的相片 */ 532 | FileHandle jpgfile = Gdx.files 533 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date 534 | + ".jpg"); 535 | Gdx.app.log("FileHandle", date); 536 | time_1 = System.currentTimeMillis(); 537 | deviceCameraControl.saveAsJpeg(jpgfile, cameraPixmap); 538 | time_2 = System.currentTimeMillis(); 539 | /* 可以得到35830ms=35s,所以非常忙,导致Mode非常缓慢的回到Mode.normal */ 540 | Gdx.app.log("cost", String.valueOf(time_2 - time_1)); 541 | deviceCameraControl.stopPreviewAsync(); 542 | ``` 543 | **混合两个pixmap** 544 | 545 | 接下来是整合两个PIxmap对象,LibGDX Pixmap对象可以帮助我们实现这个功能,但是因为相机的相片可能有不同的aspect ratio,所以我们也需要分别对待处理 546 | 547 | ```java 548 | private void merge2Pixmaps(Pixmap mainPixmap, Pixmap overlayedPixmap) { 549 | // merge to data and Gdx screen shot - but fix Aspect Ratio issues between the screen and the camera 550 | Pixmap.setFilter(Filter.BiLinear); 551 | float mainPixmapAR = (float)mainPixmap.getWidth() / mainPixmap.getHeight(); 552 | float overlayedPixmapAR = (float)overlayedPixmap.getWidth() / overlayedPixmap.getHeight(); 553 | if (overlayedPixmapAR < mainPixmapAR) { 554 | int overlayNewWidth = (int)(((float)mainPixmap.getHeight() / overlayedPixmap.getHeight()) * overlayedPixmap.getWidth()); 555 | int overlayStartX = (mainPixmap.getWidth() - overlayNewWidth)/2; 556 | mainPixmap.drawPixmap(overlayedPixmap, 557 | 0, 558 | 0, 559 | overlayedPixmap.getWidth(), 560 | overlayedPixmap.getHeight(), 561 | overlayStartX, 562 | 0, 563 | overlayNewWidth, 564 | mainPixmap.getHeight()); 565 | } else { 566 | int overlayNewHeight = (int)(((float)mainPixmap.getWidth() / overlayedPixmap.getWidth()) * overlayedPixmap.getHeight()); 567 | int overlayStartY = (mainPixmap.getHeight() - overlayNewHeight)/2; 568 | mainPixmap.drawPixmap(overlayedPixmap, 569 | 0, 570 | 0, 571 | overlayedPixmap.getWidth(), 572 | overlayedPixmap.getHeight(), 573 | 0, 574 | overlayStartY, 575 | mainPixmap.getWidth(), 576 | overlayNewHeight); 577 | } 578 | } 579 | ``` 580 | **将图片保存为jpg** 581 | 582 | 所以我们选择JPG格式进行保存,一种方式就是使用Android的bitmap类对图片进行jpg格式的保存,这个功能可以在AndroidDeviceController类中实现,因为它是Android特有的功能,所以我们想不用它。 583 | 尽量将大部分代码全部放到libgdx框架中,就是大部分实现的代码要在core中,然而libgdx的pixel格式是RGBA,而bitmap的Pixmap格式是ARGB,所以我们需要一bit一bit的将颜色转换过来 584 | 585 | 586 | ```java 587 | @Override 588 | public void saveAsJpeg(FileHandle jpgfile, Pixmap pixmap) { 589 | FileOutputStream fos; 590 | int x=0,y=0; 591 | int xl=0,yl=0; 592 | try { 593 | Bitmap bmp = Bitmap.createBitmap(pixmap.getWidth(), pixmap.getHeight(), Bitmap.Config.ARGB_8888); 594 | // we need to switch between LibGDX RGBA format to Android ARGB format 595 | for (x=0,xl=pixmap.getWidth(); x ARGB 599 | int RGB = color >> 8; 600 | int A = (color & 0x000000ff) << 24; 601 | int ARGB = A | RGB; 602 | bmp.setPixel(x, y, ARGB); 603 | } 604 | } 605 | // Finished Color format conversion 606 | fos = new FileOutputStream(jpgfile.file()); 607 | bmp.compress(CompressFormat.JPEG, 90, fos); 608 | // Finished Comression to JPEG file 609 | fos.close(); 610 | } catch (FileNotFoundException e) { 611 | e.printStackTrace(); 612 | } catch (IOException e) { 613 | e.printStackTrace(); 614 | } catch (IllegalArgumentException e) { 615 | e.printStackTrace(); 616 | } 617 | } 618 | ``` 619 | **停止预览** 620 | 621 | 在完成保存图片后,我们将停止预览窗口,并且从Activity窗口中移去CameraSurface,我们同样也将停止camera继续想camera surface继续发送preview,我们同样异步执行这些。 622 | 623 | 624 | ```java 625 | @Override 626 | public synchronized void stopPreviewAsync() { 627 | Runnable r = new Runnable() { 628 | public void run() { 629 | stopPreview(); 630 | } 631 | }; 632 | activity.post(r); 633 | } 634 | @Override 635 | public synchronized void stopPreview() { 636 | // stop previewing. 637 | if (cameraSurface != null) { 638 | if (cameraSurface.getCamera() != null) { 639 | cameraSurface.getCamera().stopPreview(); 640 | } 641 | ViewParent parentView = cameraSurface.getParent(); 642 | if (parentView instanceof ViewGroup) { 643 | ViewGroup viewGroup = (ViewGroup) parentView; 644 | viewGroup.removeView(cameraSurface); 645 | } 646 | } 647 | } 648 | ``` 649 | 650 | 注意在合成两张pixmap也就是混合相机取景和libgdx截图时分辨率有差异。在我们的Pixmaps整合过程中依然还存在一个问题,就是相机的分辨率和我们的截图分辨率也许是不同的(我在我的三星手机上,我把一个480x320屏幕截图延伸到2560x1920 大小的图片)。一个围绕它的解决方法就是扩大Libgdx视图的尺寸到更大,比实际物理设备的尺寸要大,要实现他需要使用setFixedSize()功能。真实的屏幕尺寸是根据BPU内存。 651 | 然而,在这个时间中我设法去设置虚拟屏幕尺寸为960x640(可能因为GPU显存已经被origin的带下分配了) 652 | 653 | 654 | ```java 655 | public void setFixedSize(int width, int height) { 656 | if (graphics.getView() instanceof SurfaceView) { 657 | SurfaceView glView = (SurfaceView) graphics.getView(); 658 | glView.getHolder().setFixedSize(width, height); 659 | glView.getHolder().setFormat(PixelFormat.TRANSLUCENT); 660 | } 661 | } 662 | public void restoreFixedSize() { 663 | if (graphics.getView() instanceof SurfaceView) { 664 | SurfaceView glView = (SurfaceView) graphics.getView(); 665 | glView.getHolder().setFixedSize(origWidth, origHeight); 666 | glView.getHolder().setFormat(PixelFormat.TRANSLUCENT); 667 | } 668 | } 669 | ``` 670 | **一些小提示** 671 | 672 | 1. 提示1 673 | 注意,代码仅仅适用于Android平台,并非跨平台解决方法,但是我觉得至少在桌面端,应该可以提供类似功能的代码 674 | 2. 提示2 675 | 在整合图片,并将图片数据保存到存储器上时,会花大量的时间,是因为libgdx颜色方案是RGBA而bitmap颜色方案是ARGB 676 | 3. 提示3 677 | 最后需要注意的 678 | 我仅仅测试了一部分Android设备,不同的GPU会产生不同的现象。 679 | **完整代码已上传github** 680 | [https://github.com/54wall/LibgdxAndroidCamera](https://github.com/54wall/LibgdxAndroidCamera) 681 | 最后的截图,按下camera可以开启相机,看下shot,就是进行拍摄,move可以控制猫向右侧移动 682 | 683 | ![](https://github.com/54wall/LibgdxAndroidCamera/blob/master/readme_img/4.jpg) 684 | -------------------------------------------------------------------------------- /android/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 24 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /android/assets/badlogic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/013d407bf363305f0fda6cbb4877f48527657439/android/assets/badlogic.jpg -------------------------------------------------------------------------------- /android/assets/data/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/013d407bf363305f0fda6cbb4877f48527657439/android/assets/data/bg.png -------------------------------------------------------------------------------- /android/assets/data/cat_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/013d407bf363305f0fda6cbb4877f48527657439/android/assets/data/cat_0.png -------------------------------------------------------------------------------- /android/assets/data/cat_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/013d407bf363305f0fda6cbb4877f48527657439/android/assets/data/cat_1.png -------------------------------------------------------------------------------- /android/assets/data/cat_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/013d407bf363305f0fda6cbb4877f48527657439/android/assets/data/cat_2.png -------------------------------------------------------------------------------- /android/assets/data/cat_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/013d407bf363305f0fda6cbb4877f48527657439/android/assets/data/cat_3.png -------------------------------------------------------------------------------- /android/assets/data/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/013d407bf363305f0fda6cbb4877f48527657439/android/assets/data/play.png -------------------------------------------------------------------------------- /android/assets/data/start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/013d407bf363305f0fda6cbb4877f48527657439/android/assets/data/start.png -------------------------------------------------------------------------------- /android/assets/data/takepictures.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/013d407bf363305f0fda6cbb4877f48527657439/android/assets/data/takepictures.png -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | android { 2 | buildToolsVersion "23.0.1" 3 | compileSdkVersion 20 4 | sourceSets { 5 | main { 6 | manifest.srcFile 'AndroidManifest.xml' 7 | java.srcDirs = ['src'] 8 | aidl.srcDirs = ['src'] 9 | renderscript.srcDirs = ['src'] 10 | res.srcDirs = ['res'] 11 | assets.srcDirs = ['assets'] 12 | jniLibs.srcDirs = ['libs'] 13 | } 14 | 15 | instrumentTest.setRoot('tests') 16 | } 17 | defaultConfig { 18 | applicationId "pri.weiqiang.camera" 19 | minSdkVersion 8 20 | targetSdkVersion 20 21 | } 22 | } 23 | 24 | 25 | // called every time gradle gets executed, takes the native dependencies of 26 | // the natives configuration, and extracts them to the proper libs/ folders 27 | // so they get packed with the APK. 28 | task copyAndroidNatives() { 29 | file("libs/armeabi/").mkdirs(); 30 | file("libs/armeabi-v7a/").mkdirs(); 31 | file("libs/arm64-v8a/").mkdirs(); 32 | file("libs/x86_64/").mkdirs(); 33 | file("libs/x86/").mkdirs(); 34 | 35 | configurations.natives.files.each { jar -> 36 | def outputDir = null 37 | if(jar.name.endsWith("natives-arm64-v8a.jar")) outputDir = file("libs/arm64-v8a") 38 | if(jar.name.endsWith("natives-armeabi-v7a.jar")) outputDir = file("libs/armeabi-v7a") 39 | if(jar.name.endsWith("natives-armeabi.jar")) outputDir = file("libs/armeabi") 40 | if(jar.name.endsWith("natives-x86_64.jar")) outputDir = file("libs/x86_64") 41 | if(jar.name.endsWith("natives-x86.jar")) outputDir = file("libs/x86") 42 | if(outputDir != null) { 43 | copy { 44 | from zipTree(jar) 45 | into outputDir 46 | include "*.so" 47 | } 48 | } 49 | } 50 | } 51 | 52 | task run(type: Exec) { 53 | def path 54 | def localProperties = project.file("../local.properties") 55 | if (localProperties.exists()) { 56 | Properties properties = new Properties() 57 | localProperties.withInputStream { instr -> 58 | properties.load(instr) 59 | } 60 | def sdkDir = properties.getProperty('sdk.dir') 61 | if (sdkDir) { 62 | path = sdkDir 63 | } else { 64 | path = "$System.env.ANDROID_HOME" 65 | } 66 | } else { 67 | path = "$System.env.ANDROID_HOME" 68 | } 69 | 70 | def adb = path + "/platform-tools/adb" 71 | commandLine "$adb", 'shell', 'am', 'start', '-n', 'pri.weiqiang.camera/pri.weiqiang.camera.AndroidLauncher' 72 | } 73 | 74 | // sets up the Android Eclipse project, using the old Ant based build. 75 | eclipse { 76 | // need to specify Java source sets explicitly, SpringSource Gradle Eclipse plugin 77 | // ignores any nodes added in classpath.file.withXml 78 | sourceSets { 79 | main { 80 | java.srcDirs "src", 'gen' 81 | } 82 | } 83 | 84 | jdt { 85 | sourceCompatibility = 1.6 86 | targetCompatibility = 1.6 87 | } 88 | 89 | classpath { 90 | plusConfigurations += [ project.configurations.compile ] 91 | containers 'com.android.ide.eclipse.adt.ANDROID_FRAMEWORK', 'com.android.ide.eclipse.adt.LIBRARIES' 92 | } 93 | 94 | project { 95 | name = appName + "-android" 96 | natures 'com.android.ide.eclipse.adt.AndroidNature' 97 | buildCommands.clear(); 98 | buildCommand "com.android.ide.eclipse.adt.ResourceManagerBuilder" 99 | buildCommand "com.android.ide.eclipse.adt.PreCompilerBuilder" 100 | buildCommand "org.eclipse.jdt.core.javabuilder" 101 | buildCommand "com.android.ide.eclipse.adt.ApkBuilder" 102 | } 103 | } 104 | 105 | // sets up the Android Idea project, using the old Ant based build. 106 | idea { 107 | module { 108 | sourceDirs += file("src"); 109 | scopes = [ COMPILE: [plus:[project.configurations.compile]]] 110 | 111 | iml { 112 | withXml { 113 | def node = it.asNode() 114 | def builder = NodeBuilder.newInstance(); 115 | builder.current = node; 116 | builder.component(name: "FacetManager") { 117 | facet(type: "android", name: "Android") { 118 | configuration { 119 | option(name: "UPDATE_PROPERTY_FILES", value:"true") 120 | } 121 | } 122 | } 123 | } 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /android/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/013d407bf363305f0fda6cbb4877f48527657439/android/ic_launcher-web.png -------------------------------------------------------------------------------- /android/proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | 22 | -verbose 23 | 24 | -dontwarn android.support.** 25 | -dontwarn com.badlogic.gdx.backends.android.AndroidFragmentApplication 26 | -dontwarn com.badlogic.gdx.utils.GdxBuild 27 | -dontwarn com.badlogic.gdx.physics.box2d.utils.Box2DBuild 28 | -dontwarn com.badlogic.gdx.jnigen.BuildTarget* 29 | -dontwarn com.badlogic.gdx.graphics.g2d.freetype.FreetypeBuild 30 | 31 | -keep class com.badlogic.gdx.controllers.android.AndroidControllers 32 | 33 | -keepclassmembers class com.badlogic.gdx.backends.android.AndroidInput* { 34 | (com.badlogic.gdx.Application, android.content.Context, java.lang.Object, com.badlogic.gdx.backends.android.AndroidApplicationConfiguration); 35 | } 36 | 37 | -keepclassmembers class com.badlogic.gdx.physics.box2d.World { 38 | boolean contactFilter(long, long); 39 | void beginContact(long); 40 | void endContact(long); 41 | void preSolve(long, long); 42 | void postSolve(long, long); 43 | boolean reportFixture(long); 44 | float reportRayFixture(long, float, float, float, float, float); 45 | } 46 | -------------------------------------------------------------------------------- /android/project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-19 15 | -------------------------------------------------------------------------------- /android/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/013d407bf363305f0fda6cbb4877f48527657439/android/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/013d407bf363305f0fda6cbb4877f48527657439/android/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/013d407bf363305f0fda6cbb4877f48527657439/android/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/013d407bf363305f0fda6cbb4877f48527657439/android/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | AndroidCamera 5 | 6 | 7 | -------------------------------------------------------------------------------- /android/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /android/src/pri/weiqiang/camera/AndroidDeviceCameraController.java: -------------------------------------------------------------------------------- 1 | package pri.weiqiang.camera; 2 | 3 | import java.io.FileNotFoundException; 4 | import java.io.FileOutputStream; 5 | import java.io.IOException; 6 | import java.util.List; 7 | import com.badlogic.gdx.files.FileHandle; 8 | import com.badlogic.gdx.graphics.Pixmap; 9 | import pri.weiqiang.camera.DeviceCameraControl; 10 | 11 | 12 | import android.content.Context; 13 | import android.graphics.Bitmap; 14 | import android.graphics.Bitmap.CompressFormat; 15 | import android.hardware.Camera; 16 | import android.hardware.Camera.PictureCallback; 17 | import android.hardware.Camera.ShutterCallback; 18 | import android.view.ViewGroup; 19 | import android.view.ViewParent; 20 | import android.widget.FrameLayout; 21 | 22 | public class AndroidDeviceCameraController implements DeviceCameraControl, 23 | Camera.PictureCallback, Camera.AutoFocusCallback { 24 | 25 | private static final int ONE_SECOND_IN_MILI = 1000; 26 | private final AndroidLauncher activity; 27 | private CameraSurface cameraSurface; 28 | private byte[] pictureData; 29 | private Context context; 30 | 31 | public AndroidDeviceCameraController(AndroidLauncher activity) { 32 | this.activity = activity; 33 | } 34 | 35 | @Override 36 | public synchronized void prepareCamera() { 37 | // activity.setFixedSize(960, 640);//new 38 | // activity.setFixedSize(480, 320);//54wall 39 | if (cameraSurface == null) { 40 | cameraSurface = new CameraSurface(activity); 41 | } 42 | //可以控制摄像头预览窗口大小 43 | // activity.addContentView(cameraSurface, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); 44 | // activity.addContentView(cameraSurface, new LayoutParams(960, 640)); 45 | /*http://blog.csdn.net/drrlalala/article/details/38332017*/ 46 | FrameLayout.LayoutParams params = new FrameLayout.LayoutParams 47 | (680,680); 48 | //设置顶部,左边布局 49 | // params.gravity=Gravity.CENTER_HORIZONTAL|Gravity.RIGHT; 50 | // params.gravity=Gravity.LEFT|Gravity.RIGHT; 51 | params.rightMargin=150;//可以通过设置rightMargin控制组件的实际位置 52 | params.leftMargin=200;//可以通过设置rightMargin控制组件的实际位置 53 | params.topMargin=100; 54 | activity.addContentView(cameraSurface, params); 55 | 56 | 57 | } 58 | 59 | @Override 60 | public synchronized void startPreview() { 61 | // ...and start previewing. From now on, the camera keeps pushing preview images to the surface. 62 | if (cameraSurface != null && cameraSurface.getCamera() != null) { 63 | cameraSurface.getCamera().startPreview(); 64 | } 65 | } 66 | 67 | @Override 68 | public synchronized void stopPreview() { 69 | // stop previewing. 70 | if (cameraSurface != null) { 71 | ViewParent parentView = cameraSurface.getParent(); 72 | if (parentView instanceof ViewGroup) { 73 | ViewGroup viewGroup = (ViewGroup) parentView; 74 | viewGroup.removeView(cameraSurface); 75 | } 76 | if (cameraSurface.getCamera() != null) { 77 | cameraSurface.getCamera().stopPreview(); 78 | } 79 | } 80 | activity.restoreFixedSize(); 81 | } 82 | 83 | public void setCameraParametersForPicture(Camera camera) { 84 | // Before we take the picture - we make sure all camera parameters are 85 | // as we like them 86 | // Use max resolution and auto focus 87 | Camera.Parameters p = camera.getParameters(); 88 | List supportedSizes = p.getSupportedPictureSizes(); 89 | int maxSupportedWidth = -1; 90 | int maxSupportedHeight = -1; 91 | for (Camera.Size size : supportedSizes) { 92 | if (size.width > maxSupportedWidth) { 93 | maxSupportedWidth = size.width; 94 | maxSupportedHeight = size.height; 95 | } 96 | } 97 | p.setPictureSize(maxSupportedWidth, maxSupportedHeight); 98 | p.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); 99 | camera.setParameters(p); 100 | } 101 | 102 | @Override 103 | public synchronized void takePicture() { 104 | // the user request to take a picture - start the process by requesting 105 | // focus 106 | setCameraParametersForPicture(cameraSurface.getCamera()); 107 | cameraSurface.getCamera().autoFocus(this); 108 | } 109 | 110 | @Override 111 | public synchronized void onAutoFocus(boolean success, Camera camera) { 112 | // Focus process finished, we now have focus (or not) 113 | if (success) { 114 | if (camera != null) { 115 | camera.stopPreview(); 116 | /*android6.0下边都是不推荐的了,具体找下相应替代语句*/ 117 | // camera.takePicture(null, null, null, this);//old 118 | // camera.takePicture(null, null, null);//54wall 119 | /*增加三个回调函数后,可以进行拍照,并且成功保存*/ 120 | // We now have focus take the actual picture 121 | camera.takePicture(shutterCallback, rawPictureCallback, jpegPictureCallback);//54wall 122 | /*54wall:末尾增加重新开始预览就可以继续预览图像了:http://www.xuebuyuan.com/1982434.html */ 123 | camera.startPreview(); 124 | 125 | } 126 | } 127 | } 128 | 129 | 130 | 131 | 132 | ShutterCallback shutterCallback = new ShutterCallback() { 133 | @Override 134 | public void onShutter() { 135 | } 136 | }; 137 | 138 | PictureCallback rawPictureCallback = new PictureCallback() { 139 | @Override 140 | public void onPictureTaken(byte[] arg0, Camera arg1) { 141 | 142 | } 143 | }; 144 | 145 | PictureCallback jpegPictureCallback = new PictureCallback() { 146 | @Override 147 | public void onPictureTaken(byte[] arg0, Camera arg1) { 148 | /*可以在Android项目中中生成图片*/ 149 | // String fileName = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) 150 | // .toString() 151 | // + File.separator 152 | // + "PicTest_" + System.currentTimeMillis() + ".jpg"; 153 | // File file = new File(fileName); 154 | // if (!file.getParentFile().exists()) { 155 | // file.getParentFile().mkdir(); 156 | // } 157 | // 158 | // try { 159 | // BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file)); 160 | // bos.write(arg0); 161 | // bos.flush(); 162 | // bos.close(); 163 | // 164 | // } catch (Exception e) { 165 | // 166 | // } 167 | /*54wall:因为在libgdx合成图像时,发现pictureData=null*/ 168 | pictureData=arg0; 169 | 170 | }; 171 | }; 172 | 173 | @Override 174 | public synchronized void onPictureTaken(byte[] pictureData, Camera camera) { 175 | // We got the picture data - keep it 176 | this.pictureData = pictureData; 177 | } 178 | 179 | @Override 180 | public synchronized byte[] getPictureData() { 181 | // Give to picture data to whom ever requested it 182 | return pictureData; 183 | } 184 | 185 | @Override 186 | public void prepareCameraAsync() { 187 | Runnable r = new Runnable() { 188 | public void run() { 189 | prepareCamera(); 190 | } 191 | }; 192 | activity.post(r); 193 | } 194 | 195 | @Override 196 | public synchronized void startPreviewAsync() { 197 | Runnable r = new Runnable() { 198 | public void run() { 199 | startPreview(); 200 | } 201 | }; 202 | activity.post(r); 203 | } 204 | 205 | @Override 206 | public synchronized void stopPreviewAsync() { 207 | Runnable r = new Runnable() { 208 | public void run() { 209 | stopPreview(); 210 | } 211 | }; 212 | activity.post(r); 213 | } 214 | 215 | @Override 216 | public synchronized byte[] takePictureAsync(long timeout) { 217 | timeout *= ONE_SECOND_IN_MILI; 218 | /*pictureData会报错*/ 219 | // pictureData = null;//old 220 | Runnable r = new Runnable() { 221 | public void run() { 222 | takePicture(); 223 | } 224 | }; 225 | activity.post(r); 226 | while (pictureData == null && timeout > 0) { 227 | try { 228 | Thread.sleep(ONE_SECOND_IN_MILI); 229 | timeout -= ONE_SECOND_IN_MILI; 230 | } catch (InterruptedException e) { 231 | // TODO Auto-generated catch block 232 | e.printStackTrace(); 233 | } 234 | } 235 | if (pictureData == null) { 236 | cameraSurface.getCamera().cancelAutoFocus(); 237 | } 238 | return pictureData; 239 | } 240 | 241 | 242 | 243 | /*在LibGDX中,图片以pixmap为存在格式,所以Android与LibGDX进行交互,必须有saveAsJpeg*/ 244 | @Override 245 | public void saveAsJpeg(FileHandle jpgfile, Pixmap pixmap) { 246 | FileOutputStream fos; 247 | int x = 0, y = 0; 248 | int xl = 0, yl = 0; 249 | try { 250 | Bitmap bmp = Bitmap.createBitmap(pixmap.getWidth(), 251 | pixmap.getHeight(), Bitmap.Config.ARGB_8888); 252 | // we need to switch between LibGDX RGBA format to Android ARGB 253 | // format 254 | for (x = 0, xl = pixmap.getWidth(); x < xl; x++) { 255 | for (y = 0, yl = pixmap.getHeight(); y < yl; y++) { 256 | int color = pixmap.getPixel(x, y); 257 | // RGBA => ARGB 258 | int RGB = color >> 8; 259 | int A = (color & 0x000000ff) << 24; 260 | int ARGB = A | RGB; 261 | bmp.setPixel(x, y, ARGB); 262 | } 263 | } 264 | fos = new FileOutputStream(jpgfile.file()); 265 | bmp.compress(CompressFormat.JPEG, 90, fos); 266 | fos.close(); 267 | } catch (FileNotFoundException e) { 268 | e.printStackTrace(); 269 | } catch (IOException e) { 270 | e.printStackTrace(); 271 | } catch (IllegalArgumentException e) { 272 | e.printStackTrace(); 273 | } 274 | } 275 | 276 | @Override 277 | public boolean isReady() { 278 | if (cameraSurface != null && cameraSurface.getCamera() != null) { 279 | return true; 280 | } 281 | return false; 282 | } 283 | } 284 | -------------------------------------------------------------------------------- /android/src/pri/weiqiang/camera/AndroidLauncher.java: -------------------------------------------------------------------------------- 1 | package pri.weiqiang.camera; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.badlogic.gdx.backends.android.AndroidApplication; 6 | import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration; 7 | import pri.weiqiang.camera.DeviceCameraControl; 8 | import pri.weiqiang.camera.AndroidCamera; 9 | 10 | import android.content.pm.ActivityInfo; 11 | import android.graphics.PixelFormat; 12 | import android.view.SurfaceView; 13 | 14 | public class AndroidLauncher extends AndroidApplication { 15 | private int origWidth; 16 | private int origHeight; 17 | @Override 18 | public void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | //强制竖屏 21 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//通过程序改变屏 22 | AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration(); 23 | //OpenGL ES 1.x support removed from libgdx(http://www.badlogicgames.com/wordpress/?p=3311) 24 | // cfg.useGL20 = false;//54wall old 25 | // we need to change the default pixel format - since it does not 26 | // include an alpha channel 27 | // we need the alpha channel so the camera preview will be seen behind 28 | // the GL scene 29 | cfg.r = 8; 30 | cfg.g = 8; 31 | cfg.b = 8; 32 | cfg.a = 8; 33 | DeviceCameraControl cameraControl = new AndroidDeviceCameraController( 34 | this); 35 | //拍照程序在AndroidDeviceCameraController,通过cameraControl传给MyGdxGame0606,进入LibGDX 36 | initialize(new AndroidCamera(cameraControl), cfg); 37 | 38 | if (graphics.getView() instanceof SurfaceView) { 39 | SurfaceView glView = (SurfaceView) graphics.getView(); 40 | // force alpha channel - I'm not sure we need this as the GL surface 41 | // is already using alpha channel 42 | glView.getHolder().setFormat(PixelFormat.TRANSLUCENT); 43 | } 44 | // we don't want the screen to turn off during the long image saving 45 | // process 46 | graphics.getView().setKeepScreenOn(true); 47 | // keep the original screen size 48 | origWidth = graphics.getWidth(); 49 | origHeight = graphics.getHeight(); 50 | } 51 | 52 | public void post(Runnable r) { 53 | handler.post(r); 54 | } 55 | 56 | public void setFixedSize(int width, int height) { 57 | if (graphics.getView() instanceof SurfaceView) { 58 | SurfaceView glView = (SurfaceView) graphics.getView(); 59 | glView.getHolder().setFormat(PixelFormat.TRANSLUCENT); 60 | glView.getHolder().setFixedSize(width, height); 61 | } 62 | } 63 | 64 | public void restoreFixedSize() { 65 | if (graphics.getView() instanceof SurfaceView) { 66 | SurfaceView glView = (SurfaceView) graphics.getView(); 67 | glView.getHolder().setFormat(PixelFormat.TRANSLUCENT); 68 | glView.getHolder().setFixedSize(origWidth, origHeight); 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /android/src/pri/weiqiang/camera/CameraSurface.java: -------------------------------------------------------------------------------- 1 | package pri.weiqiang.camera; 2 | 3 | /** 4 | * @author 54wall 5 | * @date 创建时间:2016-7-14 上午11:44:40 6 | * @version 1.0 7 | */ 8 | 9 | import java.io.IOException; 10 | import android.content.Context; 11 | import android.hardware.Camera; 12 | import android.os.Build; 13 | import android.view.SurfaceHolder; 14 | import android.view.SurfaceView; 15 | 16 | public class CameraSurface extends SurfaceView implements 17 | SurfaceHolder.Callback { 18 | private Camera camera; 19 | 20 | public CameraSurface(Context context) { 21 | super(context); 22 | // We're implementing the Callback interface and want to get notified 23 | // about certain surface events. 24 | getHolder().addCallback(this); 25 | // We're changing the surface to a PUSH surface, meaning we're receiving 26 | // all buffer data from another component - the camera, in this case. 27 | getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 28 | } 29 | public void surfaceCreated(SurfaceHolder holder) { 30 | // Once the surface is created, simply open a handle to the camera 31 | // hardware. 32 | // camera = Camera.open(); 33 | camera = Camera.open(0); 34 | camera.setDisplayOrientation(90); 35 | } 36 | 37 | public void surfaceChanged(SurfaceHolder holder, int format, int width, 38 | int height) { 39 | // This method is called when the surface changes, e.g. when it's size 40 | // is set. 41 | // We use the opportunity to initialize the camera preview display 42 | // dimensions. 43 | Camera.Parameters p = camera.getParameters(); 44 | // p.setPreviewSize(width, height);//old 会报 setParameters failed 45 | camera.setParameters(p); 46 | 47 | // We also assign the preview display to this surface... 48 | try { 49 | camera.setPreviewDisplay(holder); 50 | } catch (IOException e) { 51 | e.printStackTrace(); 52 | } 53 | } 54 | 55 | public void surfaceDestroyed(SurfaceHolder holder) { 56 | // Once the surface gets destroyed, we stop the preview mode and release 57 | // the whole camera since we no longer need it. 58 | camera.stopPreview(); 59 | camera.release(); 60 | camera = null; 61 | } 62 | 63 | public Camera getCamera() { 64 | return camera; 65 | } 66 | 67 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | mavenLocal() 4 | mavenCentral() 5 | maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:1.5.0' 9 | } 10 | } 11 | 12 | allprojects { 13 | apply plugin: "eclipse" 14 | apply plugin: "idea" 15 | 16 | version = '1.0' 17 | ext { 18 | appName = "AndroidCamera" 19 | gdxVersion = '1.9.3' 20 | roboVMVersion = '2.1.0' 21 | box2DLightsVersion = '1.4' 22 | ashleyVersion = '1.7.0' 23 | aiVersion = '1.8.0' 24 | } 25 | 26 | repositories { 27 | mavenLocal() 28 | mavenCentral() 29 | maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } 30 | maven { url "https://oss.sonatype.org/content/repositories/releases/" } 31 | } 32 | } 33 | 34 | project(":android") { 35 | apply plugin: "android" 36 | 37 | configurations { natives } 38 | 39 | dependencies { 40 | compile project(":core") 41 | compile "com.badlogicgames.gdx:gdx-backend-android:$gdxVersion" 42 | natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi" 43 | natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi-v7a" 44 | natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-arm64-v8a" 45 | natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86" 46 | natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86_64" 47 | compile "com.badlogicgames.gdx:gdx-box2d:$gdxVersion" 48 | natives "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-armeabi" 49 | natives "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-armeabi-v7a" 50 | natives "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-arm64-v8a" 51 | natives "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-x86" 52 | natives "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-x86_64" 53 | } 54 | } 55 | 56 | project(":core") { 57 | apply plugin: "java" 58 | 59 | 60 | dependencies { 61 | compile "com.badlogicgames.gdx:gdx:$gdxVersion" 62 | compile "com.badlogicgames.gdx:gdx-box2d:$gdxVersion" 63 | } 64 | } 65 | 66 | tasks.eclipse.doLast { 67 | delete ".project" 68 | } -------------------------------------------------------------------------------- /core/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "java" 2 | 3 | sourceCompatibility = 1.6 4 | [compileJava, compileTestJava]*.options*.encoding = 'UTF-8' 5 | 6 | sourceSets.main.java.srcDirs = [ "src/" ] 7 | 8 | 9 | eclipse.project { 10 | name = appName + "-core" 11 | } 12 | -------------------------------------------------------------------------------- /core/src/pri/weiqiang/camera/AndroidCamera.java: -------------------------------------------------------------------------------- 1 | package pri.weiqiang.camera; 2 | 3 | 4 | import java.nio.ByteBuffer; 5 | import java.text.SimpleDateFormat; 6 | import com.badlogic.gdx.Application; 7 | import com.badlogic.gdx.ApplicationListener; 8 | import com.badlogic.gdx.Gdx; 9 | import com.badlogic.gdx.files.FileHandle; 10 | import com.badlogic.gdx.graphics.GL20;//oldGL20 11 | import com.badlogic.gdx.graphics.PerspectiveCamera; 12 | import com.badlogic.gdx.graphics.Pixmap; 13 | import com.badlogic.gdx.graphics.Texture; 14 | import com.badlogic.gdx.graphics.Texture.TextureFilter; 15 | import com.badlogic.gdx.graphics.Pixmap.Filter; 16 | import com.badlogic.gdx.graphics.Pixmap.Format; 17 | import com.badlogic.gdx.graphics.g2d.SpriteBatch; 18 | import com.badlogic.gdx.graphics.g2d.TextureRegion; 19 | import com.badlogic.gdx.scenes.scene2d.Actor; 20 | import com.badlogic.gdx.scenes.scene2d.InputEvent; 21 | import com.badlogic.gdx.scenes.scene2d.Stage; 22 | import com.badlogic.gdx.scenes.scene2d.ui.Button; 23 | import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; 24 | import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; 25 | import com.badlogic.gdx.utils.viewport.StretchViewport; 26 | 27 | public class AndroidCamera implements ApplicationListener { 28 | /* http://blog.csdn.net/xietansheng/article/details/50187861 */ 29 | private Stage stage;// 舞台 30 | private Texture actorTexture; 31 | private Texture move_1_Texture; 32 | private Texture move_2_Texture; 33 | private Texture upTexture; 34 | private Texture downTexture; 35 | private Button button; 36 | private Button button_1; 37 | private Button button_move; 38 | // 视口世界的宽高统使用 480 * 800, 并统一使用伸展视口(StretchViewport) 39 | public static final float WORLD_WIDTH = 480; 40 | public static final float WORLD_HEIGHT = 800; 41 | public SpriteBatch batch; 42 | public Texture texture_demo; 43 | private SimpleDateFormat sDateFormat = new SimpleDateFormat( 44 | "yyyy-MM-dd hh:mm:ss"); 45 | private String date = sDateFormat.format(new java.util.Date()); 46 | public enum Mode { 47 | normal, prepare, preview, takePicture, waitForPictureReady, 48 | } 49 | public int state_normal = 0; 50 | public int state_prepare = 1; 51 | private Texture texture; 52 | private PerspectiveCamera camera; 53 | private Mode mode = Mode.normal; 54 | private final DeviceCameraControl deviceCameraControl; 55 | private long time_1; 56 | private long time_2; 57 | private Actor firstActor; 58 | /* 59 | * 通过this.deviceCameraControl= 60 | * cameraControl获取Android端摄像头然后后续所有的deviceCameraControl实际调用的都是Android的东西 61 | */ 62 | public AndroidCamera(DeviceCameraControl cameraControl) { 63 | this.deviceCameraControl = cameraControl; 64 | } 65 | 66 | @Override 67 | public void create() { 68 | /* http://blog.csdn.net/xietansheng/article/details/50187861 */ 69 | // 设置日志输出级别 70 | Gdx.app.setLogLevel(Application.LOG_DEBUG); 71 | // 使用伸展视口(StretchViewport)创建舞台 72 | stage = new Stage(new StretchViewport(WORLD_WIDTH, WORLD_HEIGHT)); 73 | // 将输入处理设置到舞台(必须设置, 否则点击按钮没效果) 74 | Gdx.input.setInputProcessor(stage); 75 | firstActor = new Actor(); 76 | firstActor.setHeight(150); 77 | firstActor.setWidth(150); 78 | firstActor.setPosition(150, 150); 79 | move_1_Texture = new Texture(Gdx.files.internal("data/play.png")); 80 | move_2_Texture = new Texture(Gdx.files.internal("data/start.png")); 81 | actorTexture = new Texture(Gdx.files.internal("data/cat_0.png")); 82 | upTexture = new Texture(Gdx.files.internal("data/start.png")); 83 | downTexture = new Texture(Gdx.files.internal("data/takepictures.png")); 84 | //创建 ButtonStyle 85 | Button.ButtonStyle style_move = new Button.ButtonStyle(); 86 | Button.ButtonStyle style = new Button.ButtonStyle(); 87 | style_move.up=new TextureRegionDrawable(new TextureRegion(move_1_Texture)); 88 | style_move.down=new TextureRegionDrawable(new TextureRegion(move_2_Texture)); 89 | style.up = new TextureRegionDrawable(new TextureRegion(upTexture)); 90 | style.down = new TextureRegionDrawable(new TextureRegion(downTexture)); 91 | button_move = new Button(style_move); 92 | // 设置按钮的位置 93 | button_move.setPosition(150, 300); 94 | // 给按钮添加点击监听器 95 | button_move.addListener(actor_move); 96 | button = new Button(style); 97 | // 设置按钮的位置 98 | button.setPosition(50, 300); 99 | // 给按钮添加点击监听器 100 | button.addListener(preview_on); 101 | button_1 = new Button(style); 102 | // 设置按钮的位置 103 | button_1.setPosition(300, 300); 104 | // 给按钮添加点击监听器 105 | button_1.addListener(preview_on_1); 106 | //添加 button 到舞台 107 | stage.addActor(button); 108 | stage.addActor(button_1); 109 | stage.addActor(button_move); 110 | stage.addActor(firstActor); 111 | batch = new SpriteBatch(); 112 | // Load the Libgdx splash screen texture 113 | texture = new Texture(Gdx.files.internal("data/bg.png")); 114 | texture.setFilter(TextureFilter.Linear, TextureFilter.Linear); 115 | // Create the OpenGL Camera,这里指的是视角,正交视角与设备摄像头完全不是一个东西 116 | camera = new PerspectiveCamera(67.0f, 2.0f * Gdx.graphics.getWidth() 117 | / Gdx.graphics.getHeight(), 2.0f); 118 | camera.far = 100.0f; 119 | camera.near = 0.1f; 120 | camera.position.set(2.0f, 2.0f, 2.0f); 121 | camera.lookAt(0.0f, 0.0f, 0.0f); 122 | 123 | } 124 | 125 | /* 手动释放资源 */ 126 | @Override 127 | public void dispose() { 128 | /* 对应button,应用退出时释放资源 */ 129 | if (upTexture != null) { 130 | upTexture.dispose(); 131 | } 132 | if (downTexture != null) { 133 | downTexture.dispose(); 134 | } 135 | if (stage != null) { 136 | stage.dispose(); 137 | } 138 | batch.dispose(); 139 | texture.dispose(); 140 | texture = null; 141 | } 142 | 143 | @Override 144 | public void render() { 145 | // Gdx.gl20.glClearColor(0.0f, 0f, 0.0f, 0.0f);//黑 146 | // Gdx.gl.glClearColor(1, 1, 1, 1);//背景为白色 147 | Gdx.gl.glClearColor(0.57f, 0.40f, 0.55f, 1.0f);// 紫色 148 | Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);// 清屏 149 | render_preview(); 150 | 151 | } 152 | 153 | 154 | public void render_preview() { 155 | /* 我已经将preview变为takePicture状态移动到click中,实现先预览再拍照,这样便于理解相机的运行步骤 */ 156 | Gdx.gl20.glHint(GL20.GL_GENERATE_MIPMAP_HINT, GL20.GL_NICEST); 157 | if (mode == Mode.takePicture) { 158 | Gdx.gl20.glClearColor(0f, 0.0f, 0.0f, 0.0f); 159 | if (deviceCameraControl != null) { 160 | deviceCameraControl.takePicture(); 161 | } 162 | mode = Mode.waitForPictureReady; 163 | } else if (mode == Mode.waitForPictureReady) { 164 | Gdx.gl20.glClearColor(0.0f, 0f, 0.0f, 0.0f); 165 | } else if (mode == Mode.prepare) { 166 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0f, 0.6f); 167 | if (deviceCameraControl != null) { 168 | if (deviceCameraControl.isReady()) { 169 | deviceCameraControl.startPreviewAsync(); 170 | mode = Mode.preview; 171 | } 172 | } 173 | } else if (mode == Mode.preview) { 174 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0.0f, 0f); 175 | } else { 176 | /* mode = normal */ 177 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0.6f, 1.0f); 178 | 179 | } 180 | Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT); 181 | /* 下边放到texture.bind();时效果一致 */ 182 | batch.begin(); 183 | stage.act(); // 更新舞台逻辑 184 | batch.draw(texture, 0, 0, 3f*texture.getWidth(), 3f*texture.getHeight()); 185 | Gdx.app.log("", String.valueOf(texture.getWidth())); 186 | //先绘制的就先出现,所以演员在texture上边,而不是被覆盖 187 | //batch.draw(actorTexture, firstActor.getX(), firstActor.getY());//原大小 188 | batch.draw(actorTexture, firstActor.getX(), firstActor.getY(),4*actorTexture.getWidth(),4*actorTexture.getWidth());//可控制绘制图像大小 189 | button_move.draw(batch, 1.0f); 190 | stage.draw();// 绘制舞台 191 | batch.end(); 192 | Gdx.gl20.glEnable(GL20.GL_DEPTH_TEST); 193 | Gdx.gl20.glEnable(GL20.GL_TEXTURE); 194 | Gdx.gl20.glEnable(GL20.GL_TEXTURE_2D); 195 | // Gdx.gl20.glEnable(GL20.GL_LINE_SMOOTH);//old 196 | Gdx.gl20.glEnable(GL20.GL_LINE_LOOP);//54wall 197 | Gdx.gl20.glDepthFunc(GL20.GL_LEQUAL); 198 | Gdx.gl20.glClearDepthf(1.0F); 199 | camera.update(true); 200 | // camera.apply(Gdx.gl20);//old 201 | texture.bind(); 202 | 203 | if (mode == Mode.waitForPictureReady) { 204 | /*注意deviceCameraControl.getPictureData()得到的是byte[],可见整体思路就是, 205 | *将Android摄像头得到byte[],然后将byte[]转换为Pixmap,最后将pixmap存为jpg,这样不适用Android端图片保存模式, 206 | *byte[]----Pixmap----jpg 207 | */ 208 | if (deviceCameraControl.getPictureData() != null) { 209 | // camera picture was actually takentake Gdx Screenshot 210 | Pixmap screenshotPixmap = getScreenshot(0, 0, 211 | Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true); 212 | Pixmap cameraPixmap = new Pixmap( 213 | deviceCameraControl.getPictureData(), 0, 214 | deviceCameraControl.getPictureData().length); 215 | merge2Pixmaps(cameraPixmap, screenshotPixmap); 216 | // we could call PixmapIO.writePNG(pngfile, cameraPixmap); 217 | //仅保存screenshot,对同一时间的图片进行保存然后进行比较 218 | Pixmap screenshotPixmap_test = getScreenshot(0, 0, 219 | Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true); 220 | FileHandle jpgfile_screenshot = Gdx.files 221 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date 222 | + "_screenshot.jpg"); 223 | deviceCameraControl.saveAsJpeg(jpgfile_screenshot, 224 | screenshotPixmap_test); 225 | //仅保存cameraPixma,对同一时间的图片进行保存然后进行比较 226 | Pixmap cameraPixmap_test = new Pixmap( 227 | deviceCameraControl.getPictureData(), 0, 228 | deviceCameraControl.getPictureData().length); 229 | FileHandle jpgfile_cameraPixmap = Gdx.files 230 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date 231 | + "_camera.jpg"); 232 | deviceCameraControl.saveAsJpeg(jpgfile_cameraPixmap, 233 | cameraPixmap_test); 234 | //保存混合之后的相片 235 | FileHandle jpgfile = Gdx.files 236 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date 237 | + ".jpg"); 238 | Gdx.app.log("FileHandle", date); 239 | time_1 = System.currentTimeMillis(); 240 | deviceCameraControl.saveAsJpeg(jpgfile, cameraPixmap); 241 | time_2 = System.currentTimeMillis(); 242 | //可以得到35830ms=35s,所以非常忙,导致Mode非常缓慢的回到Mode.normal 243 | Gdx.app.log("cost", String.valueOf(time_2 - time_1)); 244 | deviceCameraControl.stopPreviewAsync(); 245 | //保存文件后,mode回到normal继续render循环,所以中间停顿和logcat长时间未动的其实是卡住了Org 246 | mode = Mode.normal; 247 | 248 | } 249 | } 250 | // 这个log将会一直出现,所以render其实是一直在执行 251 | // Gdx.app.log("mode", String.valueOf(i_render++)); 252 | } 253 | //注意截图与Android设备摄像传回的图像整合时并非按我所看的视角进行 254 | private Pixmap merge2Pixmaps(Pixmap mainPixmap, Pixmap overlayedPixmap) { 255 | // merge to data and Gdx screen shot - but fix Aspect Ratio issues 256 | // between the screen and the camera 257 | Pixmap.setFilter(Filter.BiLinear); 258 | float mainPixmapAR = (float) mainPixmap.getWidth() 259 | / mainPixmap.getHeight(); 260 | float overlayedPixmapAR = (float) overlayedPixmap.getWidth() 261 | / overlayedPixmap.getHeight(); 262 | if (overlayedPixmapAR < mainPixmapAR) { 263 | int overlayNewWidth = (int) (((float) mainPixmap.getHeight() / overlayedPixmap 264 | .getHeight()) * overlayedPixmap.getWidth()); 265 | int overlayStartX = (mainPixmap.getWidth() - overlayNewWidth) / 2; 266 | // Overlaying pixmaps 267 | mainPixmap.drawPixmap(overlayedPixmap, 0, 0, 268 | overlayedPixmap.getWidth(), overlayedPixmap.getHeight(), 269 | overlayStartX, 0, overlayNewWidth, mainPixmap.getHeight()); 270 | } else { 271 | int overlayNewHeight = (int) (((float) mainPixmap.getWidth() / overlayedPixmap 272 | .getWidth()) * overlayedPixmap.getHeight()); 273 | int overlayStartY = (mainPixmap.getHeight() - overlayNewHeight) / 2; 274 | // Overlaying pixmaps 275 | mainPixmap.drawPixmap(overlayedPixmap, 0, 0, 276 | overlayedPixmap.getWidth(), overlayedPixmap.getHeight(), 0, 277 | overlayStartY, mainPixmap.getWidth(), overlayNewHeight); 278 | } 279 | return mainPixmap; 280 | } 281 | 282 | public Pixmap getScreenshot(int x, int y, int w, int h, boolean flipY) { 283 | 284 | Gdx.gl.glPixelStorei(GL20.GL_PACK_ALIGNMENT, 1); 285 | final Pixmap pixmap = new Pixmap(w, h, Format.RGBA8888); 286 | ByteBuffer pixels = pixmap.getPixels(); 287 | Gdx.gl.glReadPixels(x, y, w, h, GL20.GL_RGBA, GL20.GL_UNSIGNED_BYTE, 288 | pixels); 289 | 290 | final int numBytes = w * h * 4; 291 | byte[] lines = new byte[numBytes]; 292 | if (flipY) { 293 | final int numBytesPerLine = w * 4; 294 | for (int i = 0; i < h; i++) { 295 | pixels.position((h - i - 1) * numBytesPerLine); 296 | pixels.get(lines, i * numBytesPerLine, numBytesPerLine); 297 | } 298 | pixels.clear(); 299 | pixels.put(lines); 300 | } else { 301 | pixels.clear(); 302 | pixels.get(lines); 303 | } 304 | 305 | return pixmap; 306 | } 307 | 308 | @Override 309 | public void resize(int width, int height) { 310 | camera = new PerspectiveCamera(67.0f, 2.0f * width / height, 2.0f); 311 | camera.far = 100.0f; 312 | camera.near = 0.1f; 313 | camera.position.set(2.0f, 2.0f, 2.0f); 314 | camera.lookAt(0.0f, 0.0f, 0.0f); 315 | 316 | } 317 | 318 | @Override 319 | public void pause() { 320 | } 321 | 322 | @Override 323 | public void resume() { 324 | } 325 | 326 | ClickListener preview_on = new ClickListener() { 327 | 328 | @Override 329 | public void clicked(InputEvent event, float x, float y) { 330 | Gdx.app.log("preview_on", "preview_on按钮被点击了"); 331 | if (mode == Mode.waitForPictureReady) { 332 | mode = Mode.normal; 333 | } 334 | if (mode == Mode.normal) { 335 | mode = Mode.prepare; 336 | if (deviceCameraControl != null) { 337 | deviceCameraControl.prepareCameraAsync(); 338 | } 339 | } 340 | } 341 | 342 | }; 343 | 344 | //控制人物移动 345 | ClickListener actor_move = new ClickListener() { 346 | 347 | @Override 348 | public void clicked(InputEvent event, float x, float y) { 349 | firstActor.setX(firstActor.getX() + 55); 350 | Gdx.app.log("actor_move", "actor_move按钮被点击了"); 351 | } 352 | 353 | }; 354 | 355 | ClickListener preview_on_1 = new ClickListener() { 356 | 357 | @Override 358 | public void clicked(InputEvent event, float x, float y) { 359 | Gdx.app.log("preview_on_1", "preview_on_1按钮被点击了"); 360 | if (mode == Mode.preview) { 361 | mode = Mode.takePicture; 362 | } 363 | 364 | } 365 | 366 | }; 367 | 368 | ClickListener preview_off = new ClickListener() { 369 | @Override 370 | public void clicked(InputEvent event, float x, float y) { 371 | Gdx.app.log("preview_on", "1按钮被点击了"); 372 | if (mode == Mode.waitForPictureReady) { 373 | mode = Mode.normal; 374 | } 375 | 376 | if (mode == Mode.normal) { 377 | mode = Mode.prepare; 378 | if (deviceCameraControl != null) { 379 | deviceCameraControl.prepareCameraAsync(); 380 | } 381 | } 382 | 383 | } 384 | }; 385 | 386 | } 387 | -------------------------------------------------------------------------------- /core/src/pri/weiqiang/camera/DeviceCameraControl.java: -------------------------------------------------------------------------------- 1 | package pri.weiqiang.camera; 2 | 3 | import com.badlogic.gdx.files.FileHandle; 4 | import com.badlogic.gdx.graphics.Pixmap; 5 | 6 | /** 7 | * @author 54wall 8 | * @date 创建时间:2016-7-14 下午12:38:29 9 | * @version 1.0 10 | */ 11 | public interface DeviceCameraControl { 12 | 13 | // Synchronous interface 14 | void prepareCamera(); 15 | void startPreview(); 16 | void stopPreview(); 17 | void takePicture(); 18 | byte[] getPictureData(); 19 | // Asynchronous interface - need when called from a non platform thread (GDXOpenGl thread) 20 | void startPreviewAsync(); 21 | void stopPreviewAsync(); 22 | byte[] takePictureAsync(long timeout); 23 | void saveAsJpeg(FileHandle jpgfile, Pixmap cameraPixmap); 24 | boolean isReady(); 25 | void prepareCameraAsync(); 26 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.daemon=true 2 | org.gradle.jvmargs=-Xms128m -Xmx1500m 3 | org.gradle.configureondemand=true 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/013d407bf363305f0fda6cbb4877f48527657439/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Sep 21 13:08:26 CEST 2013 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=http\://services.gradle.org/distributions/gradle-2.10-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /old_version/README.md: -------------------------------------------------------------------------------- 1 | 为调试代码,仅留备忘使用! -------------------------------------------------------------------------------- /old_version/android/src/com/mygdx/game0606/android/AndroidDeviceCameraController.java: -------------------------------------------------------------------------------- 1 | package com.mygdx.game0606.android; 2 | 3 | /** 4 | * @author 54wall 5 | * @date 创建时间:2016-7-14 上午11:45:41 6 | * @version 1.0 7 | */ 8 | import java.io.BufferedOutputStream; 9 | import java.io.File; 10 | import java.io.FileNotFoundException; 11 | import java.io.FileOutputStream; 12 | import java.io.IOException; 13 | import java.util.List; 14 | import com.badlogic.gdx.files.FileHandle; 15 | import com.badlogic.gdx.graphics.Pixmap; 16 | import com.mygdx.game0606.DeviceCameraControl; 17 | 18 | 19 | import android.content.Context; 20 | import android.graphics.Bitmap; 21 | import android.graphics.Bitmap.CompressFormat; 22 | import android.hardware.Camera; 23 | import android.hardware.Camera.PictureCallback; 24 | import android.hardware.Camera.ShutterCallback; 25 | import android.os.Environment; 26 | import android.text.Layout; 27 | import android.view.Gravity; 28 | import android.view.ViewGroup; 29 | import android.view.ViewParent; 30 | import android.view.ViewGroup.LayoutParams; 31 | import android.widget.Button; 32 | import android.widget.FrameLayout; 33 | import android.widget.RelativeLayout; 34 | import android.widget.Toast; 35 | 36 | public class AndroidDeviceCameraController implements DeviceCameraControl, 37 | Camera.PictureCallback, Camera.AutoFocusCallback { 38 | 39 | private static final int ONE_SECOND_IN_MILI = 1000; 40 | private final AndroidLauncher activity; 41 | private CameraSurface cameraSurface; 42 | private byte[] pictureData; 43 | private Context context; 44 | 45 | public AndroidDeviceCameraController(AndroidLauncher activity) { 46 | this.activity = activity; 47 | } 48 | 49 | @Override 50 | public synchronized void prepareCamera() { 51 | // activity.setFixedSize(960, 640);//new 52 | // activity.setFixedSize(480, 320);//54wall 53 | if (cameraSurface == null) { 54 | cameraSurface = new CameraSurface(activity); 55 | } 56 | /*可以控制摄像头预览窗口大小*/ 57 | // activity.addContentView(cameraSurface, new LayoutParams( 58 | // LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); 59 | /*activity.addContentView只能有一个否则报错: 60 | * java.lang.IllegalStateException: The specified child already has a parent. 61 | * You must call removeView() on the child's parent first. 62 | * 这也是在core代码中libgdx只能在render中调用AndroidDeviceCameraController中开启相机的原因*/ 63 | // activity.addContentView(cameraSurface, new LayoutParams( 64 | // 960, 640)); 65 | 66 | 67 | 68 | /*http://blog.csdn.net/drrlalala/article/details/38332017*/ 69 | FrameLayout.LayoutParams params = new FrameLayout.LayoutParams 70 | (680,680); 71 | //设置顶部,左边布局 72 | // params.gravity=Gravity.CENTER_HORIZONTAL|Gravity.RIGHT; 73 | // params.gravity=Gravity.LEFT|Gravity.RIGHT; 74 | params.rightMargin=150;//可以通过设置rightMargin控制组件的实际位置 75 | params.leftMargin=200;//可以通过设置rightMargin控制组件的实际位置 76 | params.topMargin=100; 77 | activity.addContentView(cameraSurface, params); 78 | 79 | 80 | } 81 | 82 | @Override 83 | public synchronized void startPreview() { 84 | // ...and start previewing. From now on, the camera keeps pushing preview images to the surface. 85 | if (cameraSurface != null && cameraSurface.getCamera() != null) { 86 | cameraSurface.getCamera().startPreview(); 87 | } 88 | } 89 | 90 | @Override 91 | public synchronized void stopPreview() { 92 | // stop previewing. 93 | if (cameraSurface != null) { 94 | ViewParent parentView = cameraSurface.getParent(); 95 | if (parentView instanceof ViewGroup) { 96 | ViewGroup viewGroup = (ViewGroup) parentView; 97 | viewGroup.removeView(cameraSurface); 98 | } 99 | if (cameraSurface.getCamera() != null) { 100 | cameraSurface.getCamera().stopPreview(); 101 | } 102 | } 103 | activity.restoreFixedSize(); 104 | } 105 | 106 | public void setCameraParametersForPicture(Camera camera) { 107 | // Before we take the picture - we make sure all camera parameters are 108 | // as we like them 109 | // Use max resolution and auto focus 110 | Camera.Parameters p = camera.getParameters(); 111 | List supportedSizes = p.getSupportedPictureSizes(); 112 | int maxSupportedWidth = -1; 113 | int maxSupportedHeight = -1; 114 | for (Camera.Size size : supportedSizes) { 115 | if (size.width > maxSupportedWidth) { 116 | maxSupportedWidth = size.width; 117 | maxSupportedHeight = size.height; 118 | } 119 | } 120 | p.setPictureSize(maxSupportedWidth, maxSupportedHeight); 121 | p.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); 122 | camera.setParameters(p); 123 | } 124 | 125 | @Override 126 | public synchronized void takePicture() { 127 | // the user request to take a picture - start the process by requesting 128 | // focus 129 | setCameraParametersForPicture(cameraSurface.getCamera()); 130 | cameraSurface.getCamera().autoFocus(this); 131 | } 132 | 133 | @Override 134 | public synchronized void onAutoFocus(boolean success, Camera camera) { 135 | // Focus process finished, we now have focus (or not) 136 | if (success) { 137 | if (camera != null) { 138 | camera.stopPreview(); 139 | // We now have focus take the actual picture 140 | /*android6.0下边都是不推荐的了,具体找下相应替代语句*/ 141 | // camera.takePicture(null, null, null, this);//old 142 | // camera.takePicture(null, null, null);//54wall new 143 | /*增加三个回调函数后,可以进行拍照,并且成功保存*/ 144 | camera.takePicture(shutterCallback, rawPictureCallback, jpegPictureCallback);//54wall new 145 | /*54wall:末尾增加重新开始预览就可以继续预览图像了:http://www.xuebuyuan.com/1982434.html */ 146 | camera.startPreview(); 147 | 148 | } 149 | } 150 | } 151 | 152 | 153 | 154 | 155 | ShutterCallback shutterCallback = new ShutterCallback() { 156 | @Override 157 | public void onShutter() { 158 | } 159 | }; 160 | 161 | PictureCallback rawPictureCallback = new PictureCallback() { 162 | @Override 163 | public void onPictureTaken(byte[] arg0, Camera arg1) { 164 | 165 | } 166 | }; 167 | 168 | PictureCallback jpegPictureCallback = new PictureCallback() { 169 | @Override 170 | public void onPictureTaken(byte[] arg0, Camera arg1) { 171 | /*可以在Android中生成图片,也可以先LibGDX这篇教程一样,在core代码中生成图片,利用*/ 172 | // String fileName = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) 173 | // .toString() 174 | // + File.separator 175 | // + "PicTest_" + System.currentTimeMillis() + ".jpg"; 176 | // File file = new File(fileName); 177 | // if (!file.getParentFile().exists()) { 178 | // file.getParentFile().mkdir(); 179 | // } 180 | // 181 | // try { 182 | // BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file)); 183 | // bos.write(arg0); 184 | // bos.flush(); 185 | // bos.close(); 186 | // 187 | // } catch (Exception e) { 188 | // 189 | // } 190 | /*54wall:因为在libgdx合成图像时,发现pictureData=null*/ 191 | pictureData=arg0; 192 | 193 | }; 194 | }; 195 | 196 | @Override 197 | public synchronized void onPictureTaken(byte[] pictureData, Camera camera) { 198 | // We got the picture data - keep it 199 | this.pictureData = pictureData; 200 | } 201 | 202 | @Override 203 | public synchronized byte[] getPictureData() { 204 | // Give to picture data to whom ever requested it 205 | return pictureData; 206 | } 207 | 208 | @Override 209 | public void prepareCameraAsync() { 210 | Runnable r = new Runnable() { 211 | public void run() { 212 | prepareCamera(); 213 | } 214 | }; 215 | activity.post(r); 216 | } 217 | 218 | @Override 219 | public synchronized void startPreviewAsync() { 220 | Runnable r = new Runnable() { 221 | public void run() { 222 | startPreview(); 223 | } 224 | }; 225 | activity.post(r); 226 | } 227 | 228 | @Override 229 | public synchronized void stopPreviewAsync() { 230 | Runnable r = new Runnable() { 231 | public void run() { 232 | stopPreview(); 233 | } 234 | }; 235 | activity.post(r); 236 | } 237 | 238 | @Override 239 | public synchronized byte[] takePictureAsync(long timeout) { 240 | timeout *= ONE_SECOND_IN_MILI; 241 | /*pictureData会报错*/ 242 | // pictureData = null;//old 243 | Runnable r = new Runnable() { 244 | public void run() { 245 | takePicture(); 246 | } 247 | }; 248 | activity.post(r); 249 | while (pictureData == null && timeout > 0) { 250 | try { 251 | Thread.sleep(ONE_SECOND_IN_MILI); 252 | timeout -= ONE_SECOND_IN_MILI; 253 | } catch (InterruptedException e) { 254 | // TODO Auto-generated catch block 255 | e.printStackTrace(); 256 | } 257 | } 258 | if (pictureData == null) { 259 | cameraSurface.getCamera().cancelAutoFocus(); 260 | } 261 | return pictureData; 262 | } 263 | 264 | 265 | 266 | /*在LibGDX中,图片以pixmap为存在格式,所以Android与LibGDX进行交互,必须有saveAsJpeg*/ 267 | @Override 268 | public void saveAsJpeg(FileHandle jpgfile, Pixmap pixmap) { 269 | FileOutputStream fos; 270 | int x = 0, y = 0; 271 | int xl = 0, yl = 0; 272 | try { 273 | Bitmap bmp = Bitmap.createBitmap(pixmap.getWidth(), 274 | pixmap.getHeight(), Bitmap.Config.ARGB_8888); 275 | // we need to switch between LibGDX RGBA format to Android ARGB 276 | // format 277 | for (x = 0, xl = pixmap.getWidth(); x < xl; x++) { 278 | for (y = 0, yl = pixmap.getHeight(); y < yl; y++) { 279 | int color = pixmap.getPixel(x, y); 280 | // RGBA => ARGB 281 | int RGB = color >> 8; 282 | int A = (color & 0x000000ff) << 24; 283 | int ARGB = A | RGB; 284 | bmp.setPixel(x, y, ARGB); 285 | } 286 | } 287 | fos = new FileOutputStream(jpgfile.file()); 288 | bmp.compress(CompressFormat.JPEG, 90, fos); 289 | fos.close(); 290 | } catch (FileNotFoundException e) { 291 | e.printStackTrace(); 292 | } catch (IOException e) { 293 | e.printStackTrace(); 294 | } catch (IllegalArgumentException e) { 295 | e.printStackTrace(); 296 | } 297 | } 298 | 299 | @Override 300 | public boolean isReady() { 301 | if (cameraSurface != null && cameraSurface.getCamera() != null) { 302 | return true; 303 | } 304 | return false; 305 | } 306 | } 307 | -------------------------------------------------------------------------------- /old_version/android/src/com/mygdx/game0606/android/AndroidLauncher.java: -------------------------------------------------------------------------------- 1 | package com.mygdx.game0606.android; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.badlogic.gdx.backends.android.AndroidApplication; 6 | import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration; 7 | import com.mygdx.game0606.DeviceCameraControl; 8 | import com.mygdx.game0606.MyGdxGame0606; 9 | 10 | import android.content.pm.ActivityInfo; 11 | import android.graphics.PixelFormat; 12 | import android.view.SurfaceView; 13 | 14 | public class AndroidLauncher extends AndroidApplication { 15 | private int origWidth; 16 | private int origHeight; 17 | @Override 18 | public void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | //强制竖屏 21 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//通过程序改变屏 22 | AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration(); 23 | //OpenGL ES 1.x support removed from libgdx(http://www.badlogicgames.com/wordpress/?p=3311) 24 | // cfg.useGL20 = false;//54wall old 25 | // we need to change the default pixel format - since it does not 26 | // include an alpha channel 27 | // we need the alpha channel so the camera preview will be seen behind 28 | // the GL scene 29 | cfg.r = 8; 30 | cfg.g = 8; 31 | cfg.b = 8; 32 | cfg.a = 8; 33 | DeviceCameraControl cameraControl = new AndroidDeviceCameraController( 34 | this); 35 | //拍照程序在AndroidDeviceCameraController,通过cameraControl传给MyGdxGame0606,进入LibGDX 36 | initialize(new MyGdxGame0606(cameraControl), cfg); 37 | 38 | if (graphics.getView() instanceof SurfaceView) { 39 | SurfaceView glView = (SurfaceView) graphics.getView(); 40 | // force alpha channel - I'm not sure we need this as the GL surface 41 | // is already using alpha channel 42 | glView.getHolder().setFormat(PixelFormat.TRANSLUCENT); 43 | } 44 | // we don't want the screen to turn off during the long image saving 45 | // process 46 | graphics.getView().setKeepScreenOn(true); 47 | // keep the original screen size 48 | origWidth = graphics.getWidth(); 49 | origHeight = graphics.getHeight(); 50 | } 51 | 52 | public void post(Runnable r) { 53 | handler.post(r); 54 | } 55 | 56 | public void setFixedSize(int width, int height) { 57 | if (graphics.getView() instanceof SurfaceView) { 58 | SurfaceView glView = (SurfaceView) graphics.getView(); 59 | glView.getHolder().setFormat(PixelFormat.TRANSLUCENT); 60 | glView.getHolder().setFixedSize(width, height); 61 | } 62 | } 63 | 64 | public void restoreFixedSize() { 65 | if (graphics.getView() instanceof SurfaceView) { 66 | SurfaceView glView = (SurfaceView) graphics.getView(); 67 | glView.getHolder().setFormat(PixelFormat.TRANSLUCENT); 68 | glView.getHolder().setFixedSize(origWidth, origHeight); 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /old_version/android/src/com/mygdx/game0606/android/CameraSurface.java: -------------------------------------------------------------------------------- 1 | package com.mygdx.game0606.android; 2 | 3 | /** 4 | * @author 54wall 5 | * @date 创建时间:2016-7-14 上午11:44:40 6 | * @version 1.0 7 | */ 8 | 9 | import java.io.IOException; 10 | 11 | import android.annotation.TargetApi; 12 | import android.content.Context; 13 | import android.hardware.Camera; 14 | import android.os.Build; 15 | import android.view.SurfaceHolder; 16 | import android.view.SurfaceView; 17 | 18 | public class CameraSurface extends SurfaceView implements 19 | SurfaceHolder.Callback { 20 | private Camera camera; 21 | 22 | public CameraSurface(Context context) { 23 | super(context); 24 | // We're implementing the Callback interface and want to get notified 25 | // about certain surface events. 26 | getHolder().addCallback(this); 27 | // We're changing the surface to a PUSH surface, meaning we're receiving 28 | // all buffer data from another component - the camera, in this case. 29 | getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 30 | } 31 | 32 | @TargetApi(Build.VERSION_CODES.GINGERBREAD) 33 | public void surfaceCreated(SurfaceHolder holder) { 34 | // Once the surface is created, simply open a handle to the camera 35 | // hardware. 36 | // camera = Camera.open();//old 37 | camera = Camera.open(0); 38 | camera.setDisplayOrientation(90); 39 | } 40 | 41 | public void surfaceChanged(SurfaceHolder holder, int format, int width, 42 | int height) { 43 | // This method is called when the surface changes, e.g. when it's size 44 | // is set. 45 | // We use the opportunity to initialize the camera preview display 46 | // dimensions. 47 | Camera.Parameters p = camera.getParameters(); 48 | // p.setPreviewSize(width, height);//old 会报 setParameters failed 49 | camera.setParameters(p); 50 | 51 | // We also assign the preview display to this surface... 52 | try { 53 | camera.setPreviewDisplay(holder); 54 | } catch (IOException e) { 55 | e.printStackTrace(); 56 | } 57 | } 58 | 59 | public void surfaceDestroyed(SurfaceHolder holder) { 60 | // Once the surface gets destroyed, we stop the preview mode and release 61 | // the whole camera since we no longer need it. 62 | camera.stopPreview(); 63 | camera.release(); 64 | camera = null; 65 | } 66 | 67 | public Camera getCamera() { 68 | return camera; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /old_version/core/src/MyGdxGame0606.gwt.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /old_version/core/src/com/mygdx/game0606/Constant.java: -------------------------------------------------------------------------------- 1 | package com.mygdx.game0606; 2 | 3 | import com.badlogic.gdx.graphics.Color; 4 | 5 | /** 6 | * @author 54wall 7 | * @date 创建时间:2016-7-19 下午3:18:21 8 | * @version 1.0 9 | */ 10 | public class Constant { 11 | 12 | public static final float vertexData[] = { 13 | 1.0f, 14 | 1.0f, 15 | 1.0f, 16 | Color.toFloatBits(255, 255, 255, 255), 17 | 0.0f, 18 | 0.0f, // quad/face 0/Vertex 0 19 | 0.0f, 20 | 1.0f, 21 | 1.0f, 22 | Color.toFloatBits(255, 255, 255, 255), 23 | 0.0f, 24 | 1.0f, // quad/face 0/Vertex 1 25 | 0.0f, 26 | 0.0f, 27 | 1.0f, 28 | Color.toFloatBits(255, 255, 255, 255), 29 | 1.0f, 30 | 1.0f, // quad/face 0/Vertex 2 31 | 1.0f, 32 | 0.0f, 33 | 1.0f, 34 | Color.toFloatBits(255, 255, 255, 255), 35 | 1.0f, 36 | 0.0f, // quad/face 0/Vertex 3 37 | 38 | 1.0f, 39 | 1.0f, 40 | 1.0f, 41 | Color.toFloatBits(255, 255, 255, 255), 42 | 1.0f, 43 | 1.0f, // quad/face 1/Vertex 4 44 | 1.0f, 45 | 0.0f, 46 | 1.0f, 47 | Color.toFloatBits(255, 255, 255, 255), 48 | 0.0f, 49 | 1.0f, // quad/face 1/Vertex 5 50 | 1.0f, 51 | 0.0f, 52 | 0.0f, 53 | Color.toFloatBits(255, 255, 255, 255), 54 | 0.0f, 55 | 0.0f, // quad/face 1/Vertex 6 56 | 1.0f, 57 | 1.0f, 58 | 0.0f, 59 | Color.toFloatBits(255, 255, 255, 255), 60 | 1.0f, 61 | 0.0f, // quad/face 1/Vertex 7 62 | 63 | 1.0f, 64 | 1.0f, 65 | 1.0f, 66 | Color.toFloatBits(255, 255, 255, 255), 67 | 0.0f, 68 | 0.0f, // quad/face 2/Vertex 8 69 | 1.0f, 70 | 1.0f, 71 | 0.0f, 72 | Color.toFloatBits(255, 255, 255, 255), 73 | 0.0f, 74 | 1.0f, // quad/face 2/Vertex 9 75 | 0.0f, 76 | 1.0f, 77 | 0.0f, 78 | Color.toFloatBits(255, 255, 255, 255), 79 | 1.0f, 80 | 1.0f, // quad/face 2/Vertex 10 81 | 0.0f, 82 | 1.0f, 83 | 1.0f, 84 | Color.toFloatBits(255, 255, 255, 255), 85 | 1.0f, 86 | 0.0f, // quad/face 2/Vertex 11 87 | 88 | 1.0f, 89 | 0.0f, 90 | 0.0f, 91 | Color.toFloatBits(255, 255, 255, 255), 92 | 1.0f, 93 | 1.0f, // quad/face 3/Vertex 12 94 | 0.0f, 95 | 0.0f, 96 | 0.0f, 97 | Color.toFloatBits(255, 255, 255, 255), 98 | 0.0f, 99 | 1.0f, // quad/face 3/Vertex 13 100 | 0.0f, 101 | 1.0f, 102 | 0.0f, 103 | Color.toFloatBits(255, 255, 255, 255), 104 | 0.0f, 105 | 0.0f, // quad/face 3/Vertex 14 106 | 1.0f, 107 | 1.0f, 108 | 0.0f, 109 | Color.toFloatBits(255, 255, 255, 255), 110 | 1.0f, 111 | 0.0f, // quad/face 3/Vertex 15 112 | 113 | 0.0f, 114 | 1.0f, 115 | 1.0f, 116 | Color.toFloatBits(255, 255, 255, 255), 117 | 1.0f, 118 | 1.0f, // quad/face 4/Vertex 16 119 | 0.0f, 120 | 1.0f, 121 | 0.0f, 122 | Color.toFloatBits(255, 255, 255, 255), 123 | 0.0f, 124 | 1.0f, // quad/face 4/Vertex 17 125 | 0.0f, 126 | 0.0f, 127 | 0.0f, 128 | Color.toFloatBits(255, 255, 255, 255), 129 | 0.0f, 130 | 0.0f, // quad/face 4/Vertex 18 131 | 0.0f, 132 | 0.0f, 133 | 1.0f, 134 | Color.toFloatBits(255, 255, 255, 255), 135 | 1.0f, 136 | 0.0f, // quad/face 4/Vertex 19 137 | 138 | 0.0f, 0.0f, 139 | 0.0f, 140 | Color.toFloatBits(255, 255, 255, 255), 141 | 1.0f, 142 | 1.0f, // quad/face 5/Vertex 20 143 | 1.0f, 0.0f, 0.0f, 144 | Color.toFloatBits(255, 255, 255, 255), 145 | 0.0f, 146 | 1.0f, // quad/face 5/Vertex 21 147 | 1.0f, 0.0f, 1.0f, Color.toFloatBits(255, 255, 255, 255), 148 | 0.0f, 149 | 0.0f, // quad/face 5/Vertex 22 150 | 0.0f, 0.0f, 1.0f, Color.toFloatBits(255, 255, 255, 255), 1.0f, 151 | 0.0f, // quad/face 5/Vertex 23 152 | }; 153 | } 154 | -------------------------------------------------------------------------------- /old_version/core/src/com/mygdx/game0606/DeviceCameraControl.java: -------------------------------------------------------------------------------- 1 | package com.mygdx.game0606; 2 | 3 | import com.badlogic.gdx.files.FileHandle; 4 | import com.badlogic.gdx.graphics.Pixmap; 5 | 6 | /** 7 | * @author 54wall 8 | * @date 创建时间:2016-7-14 下午12:38:29 9 | * @version 1.0 10 | */ 11 | public interface DeviceCameraControl { 12 | 13 | // Synchronous interface 14 | void prepareCamera(); 15 | 16 | void startPreview(); 17 | 18 | void stopPreview(); 19 | 20 | void takePicture(); 21 | 22 | byte[] getPictureData(); 23 | 24 | // Asynchronous interface - need when called from a non platform thread (GDX 25 | // OpenGl thread) 26 | void startPreviewAsync(); 27 | 28 | void stopPreviewAsync(); 29 | 30 | byte[] takePictureAsync(long timeout); 31 | 32 | void saveAsJpeg(FileHandle jpgfile, Pixmap cameraPixmap); 33 | 34 | boolean isReady(); 35 | 36 | void prepareCameraAsync(); 37 | } -------------------------------------------------------------------------------- /old_version/core/src/com/mygdx/game0606/MyGdxGame0606.java: -------------------------------------------------------------------------------- 1 | package com.mygdx.game0606; 2 | 3 | 4 | import java.nio.ByteBuffer; 5 | import java.text.SimpleDateFormat; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | import com.badlogic.gdx.Application; 10 | import com.badlogic.gdx.ApplicationListener; 11 | import com.badlogic.gdx.Gdx; 12 | import com.badlogic.gdx.files.FileHandle; 13 | import com.badlogic.gdx.graphics.Color; 14 | import com.badlogic.gdx.graphics.GL20;//oldGL20 15 | import com.badlogic.gdx.graphics.Mesh; 16 | import com.badlogic.gdx.graphics.PerspectiveCamera; 17 | import com.badlogic.gdx.graphics.Pixmap; 18 | import com.badlogic.gdx.graphics.Texture; 19 | import com.badlogic.gdx.graphics.Texture.TextureFilter; 20 | import com.badlogic.gdx.graphics.VertexAttribute; 21 | import com.badlogic.gdx.graphics.Pixmap.Filter; 22 | import com.badlogic.gdx.graphics.Pixmap.Format; 23 | import com.badlogic.gdx.graphics.VertexAttributes.Usage; 24 | import com.badlogic.gdx.graphics.g2d.BitmapFont; 25 | import com.badlogic.gdx.graphics.g2d.SpriteBatch; 26 | import com.badlogic.gdx.graphics.g2d.TextureRegion; 27 | import com.badlogic.gdx.graphics.glutils.ShaderProgram; 28 | import com.badlogic.gdx.scenes.scene2d.Actor; 29 | import com.badlogic.gdx.scenes.scene2d.InputEvent; 30 | import com.badlogic.gdx.scenes.scene2d.Stage; 31 | import com.badlogic.gdx.scenes.scene2d.ui.Button; 32 | import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; 33 | import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; 34 | import com.badlogic.gdx.utils.viewport.StretchViewport; 35 | import com.mygdx.game0606.actor.FirstActor; 36 | 37 | public class MyGdxGame0606 implements ApplicationListener { 38 | /* http://blog.csdn.net/xietansheng/article/details/50187861 */ 39 | private Stage stage;// 舞台 40 | private Texture actorTexture; 41 | private Texture move_1_Texture; 42 | private Texture move_2_Texture; 43 | private Texture upTexture; 44 | private Texture downTexture; 45 | private Texture faceTexture; 46 | private Texture faceTexture_1; 47 | private Texture faceTexture_2; 48 | private Texture faceTexture_3; 49 | private Texture faceTexture_4; 50 | private List texturelisg=new ArrayList(); 51 | private Button button;// 按钮 52 | private Button button_1;// 按钮 53 | private Button button_move;// 按钮 54 | // 视口世界的宽高统使用 480 * 800, 并统一使用伸展视口(StretchViewport) 55 | public static final float WORLD_WIDTH = 480; 56 | public static final float WORLD_HEIGHT = 800; 57 | public SpriteBatch batch; 58 | public Texture texture_demo; 59 | private SimpleDateFormat sDateFormat = new SimpleDateFormat( 60 | "yyyy-MM-dd hh:mm:ss"); 61 | private String date = sDateFormat.format(new java.util.Date()); 62 | public enum Mode { 63 | normal, prepare, preview, takePicture, waitForPictureReady, 64 | } 65 | public int state_normal = 0; 66 | public int state_prepare = 1; 67 | public Constant constant = new Constant(); 68 | public static final short facesVerticesIndex[][] = { { 0, 1, 2, 3 }, 69 | { 4, 5, 6, 7 }, { 8, 9, 10, 11 }, { 12, 13, 14, 15 }, 70 | { 16, 17, 18, 19 }, { 20, 21, 22, 23 } }; 71 | private final static VertexAttribute verticesAttributes[] = new VertexAttribute[] { 72 | new VertexAttribute(Usage.Position, 3, "a_position"), 73 | new VertexAttribute(Usage.ColorPacked, 4, "a_color"), 74 | new VertexAttribute(Usage.TextureCoordinates, 2, "a_texCoords"), }; 75 | private Texture texture; 76 | private Mesh[] mesh = new Mesh[6]; 77 | private PerspectiveCamera camera; 78 | private Mode mode = Mode.normal; 79 | private final DeviceCameraControl deviceCameraControl; 80 | private long time_1; 81 | private long time_2; 82 | private int i_render = 0; 83 | private Actor firstActor; 84 | /* 85 | * 通过this.deviceCameraControl= 86 | * cameraControl获取Android端摄像头然后后续所有的deviceCameraControl实际调用的都是Android的东西 87 | */ 88 | public MyGdxGame0606(DeviceCameraControl cameraControl) { 89 | this.deviceCameraControl = cameraControl; 90 | } 91 | 92 | @Override 93 | public void create() { 94 | /* http://blog.csdn.net/xietansheng/article/details/50187861 */ 95 | // 设置日志输出级别 96 | Gdx.app.setLogLevel(Application.LOG_DEBUG); 97 | // 使用伸展视口(StretchViewport)创建舞台 98 | stage = new Stage(new StretchViewport(WORLD_WIDTH, WORLD_HEIGHT)); 99 | // 将输入处理设置到舞台(必须设置, 否则点击按钮没效果) 100 | Gdx.input.setInputProcessor(stage); 101 | firstActor = new Actor(); 102 | firstActor.setHeight(150); 103 | firstActor.setWidth(150); 104 | firstActor.setPosition(150, 150); 105 | move_1_Texture = new Texture(Gdx.files.internal("data/play.png")); 106 | move_2_Texture = new Texture(Gdx.files.internal("data/start.png")); 107 | actorTexture = new Texture(Gdx.files.internal("data/cat_0.png")); 108 | upTexture = new Texture(Gdx.files.internal("data/start.png")); 109 | downTexture = new Texture(Gdx.files.internal("data/takepictures.png")); 110 | // faceTexture=new Texture(Gdx.files.external("a_SDK_fail/1.jpg")); 111 | // faceTexture_1=new Texture(Gdx.files.external("a_SDK_fail/1.jpg")); 112 | // faceTexture_2=new Texture(Gdx.files.external("a_SDK_fail/2.jpg")); 113 | // faceTexture_3=new Texture(Gdx.files.external("a_SDK_fail/3.jpg")); 114 | // faceTexture_4=new Texture(Gdx.files.external("a_SDK_fail/4.jpg")); 115 | 116 | //创建 ButtonStyle 117 | Button.ButtonStyle style_move = new Button.ButtonStyle(); 118 | Button.ButtonStyle style = new Button.ButtonStyle(); 119 | style_move.up=new TextureRegionDrawable(new TextureRegion(move_1_Texture)); 120 | style_move.down=new TextureRegionDrawable(new TextureRegion(move_2_Texture)); 121 | style.up = new TextureRegionDrawable(new TextureRegion(upTexture)); 122 | style.down = new TextureRegionDrawable(new TextureRegion(downTexture)); 123 | button_move = new Button(style_move); 124 | // 设置按钮的位置 125 | button_move.setPosition(150, 300); 126 | // 给按钮添加点击监听器 127 | button_move.addListener(actor_move); 128 | button = new Button(style); 129 | // 设置按钮的位置 130 | button.setPosition(50, 300); 131 | // 给按钮添加点击监听器 132 | button.addListener(preview_on); 133 | button_1 = new Button(style); 134 | // 设置按钮的位置 135 | button_1.setPosition(300, 300); 136 | // 给按钮添加点击监听器 137 | button_1.addListener(preview_on_1); 138 | //添加 button 到舞台 139 | stage.addActor(button); 140 | stage.addActor(button_1); 141 | stage.addActor(button_move); 142 | stage.addActor(firstActor); 143 | batch = new SpriteBatch(); 144 | texture_demo = new Texture(Gdx.files.internal("data/1.png")); 145 | // Load the Libgdx splash screen texture 146 | texture = new Texture(Gdx.files.internal("data/bg.png")); 147 | texture.setFilter(TextureFilter.Linear, TextureFilter.Linear); 148 | // Create the 6 faces of the Cube 149 | for (int i = 0; i < 6; i++) { 150 | mesh[i] = new Mesh(true, 24, 4, verticesAttributes); 151 | mesh[i].setVertices(Constant.vertexData); 152 | mesh[i].setIndices(facesVerticesIndex[i]); 153 | } 154 | // Create the OpenGL Camera,这里指的是视角,正交视角与设备摄像头完全不是一个东西 155 | camera = new PerspectiveCamera(67.0f, 2.0f * Gdx.graphics.getWidth() 156 | / Gdx.graphics.getHeight(), 2.0f);// oldfloat// fieldOfViewY改为37无反应 157 | camera.far = 100.0f;// old 改为50,无反应 158 | camera.near = 0.1f; 159 | camera.position.set(2.0f, 2.0f, 2.0f); 160 | camera.lookAt(0.0f, 0.0f, 0.0f);// old 161 | 162 | } 163 | 164 | /* 手动释放资源 */ 165 | @Override 166 | public void dispose() { 167 | /* 对应button,应用退出时释放资源 */ 168 | if (upTexture != null) { 169 | upTexture.dispose(); 170 | } 171 | if (downTexture != null) { 172 | downTexture.dispose(); 173 | } 174 | if (stage != null) { 175 | stage.dispose(); 176 | } 177 | /* 54wall */ 178 | batch.dispose(); 179 | texture_demo.dispose(); 180 | 181 | texture.dispose(); 182 | for (int i = 0; i < 6; i++) { 183 | mesh[i].dispose(); 184 | mesh[i] = null; 185 | } 186 | texture = null; 187 | } 188 | 189 | /* 通过debug发现,每次点击运行(断点在render内)render都会一直运行,可见render作为渲染的一个覆盖函数的确是处于一直运行的状态 */ 190 | @Override 191 | public void render() { 192 | /*如何控制render一进入就使Android相机进入preview,直接在render加入50 100计数器,保证在50之前为mode的一个状态,随着render的进行 193 | * 计数器进行计数,然后每次只执行一次deviceCameraControl,就可以直接进入相机的预览模式*/ 194 | // Gdx.gl20.glClearColor(0.0f, 0f, 0.0f, 0.0f);//黑 195 | // Gdx.gl.glClearColor(1, 1, 1, 1);// 设置背景为白色 196 | Gdx.gl.glClearColor(0.57f, 0.40f, 0.55f, 1.0f);// 紫色 197 | Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);// 清屏 198 | /*绘制视频帧*/ 199 | i_render++; 200 | if (i_render==60) { 201 | i_render=1; 202 | } 203 | 204 | faceTexture=new Texture(Gdx.files.external("a_SDK_fail/"+i_render+".jpg")); 205 | batch.begin(); 206 | batch.draw(faceTexture, 0, 0, faceTexture.getWidth(), faceTexture.getHeight()); 207 | batch.end(); 208 | faceTexture.dispose();//没有直接gc,有了之后也有GC,但是画面依然在动 209 | /*调用Android摄像头*/ 210 | // render_preview(); 211 | 212 | } 213 | 214 | /*1 发现在打开摄像头后,button全部失效,只有没有camera预览时,button才有效,是不是渲染时摄像头与绘制的button存在冲突 215 | * 并且在调试button时,屏幕处于按压状态也是和button冲突了 216 | * 2现在实现的功能是按下左按钮,开始预览,按下右侧按钮进行聚焦拍摄,这说明在mode为preview状态时,button是可以相应的之前却一直不可以*/ 217 | public void render_preview() { 218 | /* 我已经将preview变为takePicture状态移动到click中,实现先预览再拍照 */ 219 | Gdx.gl20.glHint(GL20.GL_GENERATE_MIPMAP_HINT, GL20.GL_NICEST); 220 | if (mode == Mode.takePicture) { 221 | /* 没有清屏,摄像头的预览功能就没有,演员和舞台在各个if中可以不加 */ 222 | Gdx.gl20.glClearColor(0f, 0.0f, 0.0f, 0.0f); 223 | if (deviceCameraControl != null) { 224 | deviceCameraControl.takePicture(); 225 | } 226 | mode = Mode.waitForPictureReady; 227 | } else if (mode == Mode.waitForPictureReady) { 228 | Gdx.gl20.glClearColor(0.0f, 0f, 0.0f, 0.0f); 229 | } else if (mode == Mode.prepare) { 230 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0f, 0.6f); 231 | if (deviceCameraControl != null) { 232 | if (deviceCameraControl.isReady()) { 233 | deviceCameraControl.startPreviewAsync(); 234 | mode = Mode.preview; 235 | } 236 | } 237 | } else if (mode == Mode.preview) { 238 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0.0f, 0f); 239 | } else { 240 | /* mode = normal */ 241 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0.6f, 1.0f); 242 | 243 | } 244 | Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT); 245 | /* 下边放到texture.bind();时效果一致 */ 246 | batch.begin(); 247 | 248 | stage.act(); // 更新舞台逻辑 249 | /* 新增演员 ,放到这里才会显示*/ 250 | // batch.draw(actorTexture, 100, 300);//这么写,每次的移动无效,因为render画的动作被写死了 251 | // batch.draw(actorTexture, firstActor.getX(), firstActor.getY()); 252 | // batch.draw(texture, 480, 480, texture.getWidth(), texture.getHeight()); 253 | // batch.draw(texture, 0, 0, texture.getWidth(), texture.getHeight()); 254 | batch.draw(texture, 0, 0, 3f*texture.getWidth(), 3f*texture.getHeight()); 255 | Gdx.app.log("", String.valueOf(texture.getWidth())); 256 | //先绘制的就先出现,所以演员在texture上边,而不是被覆盖 257 | // batch.draw(actorTexture, firstActor.getX(), firstActor.getY());//原大小 258 | batch.draw(actorTexture, firstActor.getX(), firstActor.getY(),4*actorTexture.getWidth(),4*actorTexture.getWidth());//可控制绘制图像大小 259 | button.draw(batch, 1.0F);// 仅绘制actor 260 | button_1.draw(batch, 1.0F); 261 | button_move.draw(batch, 1.0f); 262 | /* 新增演员 ,放到这里不会显示*/ 263 | // batch.draw(actorTexture, 100, 300); 264 | stage.draw();// 绘制舞台 265 | // batch.draw(texture, 0, 0, 960, 540); 266 | batch.end(); 267 | Gdx.gl20.glEnable(GL20.GL_DEPTH_TEST); 268 | Gdx.gl20.glEnable(GL20.GL_TEXTURE); 269 | Gdx.gl20.glEnable(GL20.GL_TEXTURE_2D); 270 | // Gdx.gl20.glEnable(GL20.GL_LINE_SMOOTH);//54wall old 271 | Gdx.gl20.glEnable(GL20.GL_LINE_LOOP);// new 272 | Gdx.gl20.glDepthFunc(GL20.GL_LEQUAL); 273 | Gdx.gl20.glClearDepthf(1.0F); 274 | camera.update(true); 275 | // camera.apply(Gdx.gl20);//54wall old 276 | texture.bind(); 277 | 278 | if (mode == Mode.waitForPictureReady) { 279 | /*注意deviceCameraControl.getPictureData()得到的是byte[],可见整体思路就是, 280 | *将Android摄像头得到byte[],然后将byte[]转换为Pixmap,最后将pixmap存为jpg,这样不适用Android端图片保存模式, 281 | *byte[]----Pixmap----jpg 282 | */ 283 | if (deviceCameraControl.getPictureData() != null) { 284 | // camera picture was actually takentake Gdx Screenshot 285 | Pixmap screenshotPixmap = getScreenshot(0, 0, 286 | Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true); 287 | /* 开始报错deviceCameraControl.getPictureData一直未null */ 288 | Pixmap cameraPixmap = new Pixmap( 289 | deviceCameraControl.getPictureData(), 0, 290 | deviceCameraControl.getPictureData().length); 291 | merge2Pixmaps(cameraPixmap, screenshotPixmap); 292 | // we could call PixmapIO.writePNG(pngfile, cameraPixmap); 293 | /* 仅保存screenshot,对同一时间的图片进行保存然后进行比较 */ 294 | Pixmap screenshotPixmap_test = getScreenshot(0, 0, 295 | Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true); 296 | FileHandle jpgfile_screenshot = Gdx.files 297 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date 298 | + "_screenshot.jpg"); 299 | deviceCameraControl.saveAsJpeg(jpgfile_screenshot, 300 | screenshotPixmap_test); 301 | /* 仅保存cameraPixma,对同一时间的图片进行保存然后进行比较 */ 302 | Pixmap cameraPixmap_test = new Pixmap( 303 | deviceCameraControl.getPictureData(), 0, 304 | deviceCameraControl.getPictureData().length); 305 | FileHandle jpgfile_cameraPixmap = Gdx.files 306 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date 307 | + "_camera.jpg"); 308 | deviceCameraControl.saveAsJpeg(jpgfile_cameraPixmap, 309 | cameraPixmap_test); 310 | /* 保存混合之后的相片 */ 311 | FileHandle jpgfile = Gdx.files 312 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date 313 | + ".jpg"); 314 | Gdx.app.log("FileHandle", date); 315 | time_1 = System.currentTimeMillis(); 316 | deviceCameraControl.saveAsJpeg(jpgfile, cameraPixmap); 317 | time_2 = System.currentTimeMillis(); 318 | /* 可以得到35830ms=35s,所以非常忙,导致Mode非常缓慢的回到Mode.normal */ 319 | Gdx.app.log("cost", String.valueOf(time_2 - time_1)); 320 | deviceCameraControl.stopPreviewAsync(); 321 | /* 保存文件后,mode回到normal继续render循环,所以中间停顿的其实是卡住了?! */ 322 | mode = Mode.normal; 323 | 324 | } 325 | } 326 | /* 这个log将会一直出现,所以render其实是一直在执行 */ 327 | // Gdx.app.log("mode", String.valueOf(mode)); 328 | // Gdx.app.log("mode", String.valueOf(i_render++)); 329 | } 330 | /* 随手加一个log是很重要的 */ 331 | public void takePicture4render() { 332 | /* 333 | * 进入app后,手按住屏幕不放,才能进入预览模式,放开就直接拍照了 334 | * input.isTouched(1)可能与button点击存在冲突,所以必须屏蔽 335 | */ 336 | // if (Gdx.input.isTouched(1)) { 337 | // 338 | // mode = Mode.normal; 339 | // Gdx.app.log("doube", String.valueOf(mode)); 340 | // } 341 | // 342 | // 343 | // if (Gdx.input.isTouched()) { 344 | // if (mode == Mode.normal) { 345 | // mode = Mode.prepare; 346 | // if (deviceCameraControl != null) { 347 | // deviceCameraControl.prepareCameraAsync(); 348 | // } 349 | // } 350 | // } else { 351 | // // touch removed 352 | // if (mode == Mode.preview) { 353 | // mode = Mode.takePicture; 354 | // } 355 | // } 356 | 357 | /* 我想让摄像头一直处于预览状态 */ 358 | // if (deviceCameraControl != null) { 359 | // deviceCameraControl.prepareCameraAsync(); 360 | // } 361 | 362 | /* 仅跟进入预览后直接进入拍照模式 */ 363 | if (mode == Mode.preview) { 364 | mode = Mode.takePicture; 365 | } 366 | 367 | // Gdx.gl20.glHint(GL20.GL_PERSPECTIVE_CORRECTION_HINT, 368 | // GL20.GL_NICEST);//old 54wall 369 | Gdx.gl20.glHint(GL20.GL_GENERATE_MIPMAP_HINT, GL20.GL_NICEST); 370 | if (mode == Mode.takePicture) { 371 | /* 没有清屏,摄像头的预览功能就没有 */ 372 | Gdx.gl20.glClearColor(0f, 0.0f, 0.0f, 0.0f); 373 | batch.begin(); 374 | stage.act(); // 更新舞台逻辑 375 | button.draw(batch, 1.0F);// 仅绘制actor 376 | stage.draw();// 绘制舞台 377 | batch.draw(texture, 0, 0, 960, 540); 378 | batch.end(); 379 | 380 | if (deviceCameraControl != null) { 381 | deviceCameraControl.takePicture(); 382 | 383 | } 384 | mode = Mode.waitForPictureReady; 385 | } else if (mode == Mode.waitForPictureReady) { 386 | Gdx.gl20.glClearColor(0.0f, 0f, 0.0f, 0.0f); 387 | batch.begin(); 388 | stage.act(); 389 | button.draw(batch, 1.0F); 390 | stage.draw(); 391 | batch.draw(texture, 0, 0, 960, 540); 392 | batch.end(); 393 | 394 | } else if (mode == Mode.prepare) { 395 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0f, 0.0f); 396 | batch.begin(); 397 | stage.act(); 398 | button.draw(batch, 1.0F); 399 | stage.draw(); 400 | batch.draw(texture, 0, 0, 960, 540); 401 | batch.end(); 402 | if (deviceCameraControl != null) { 403 | if (deviceCameraControl.isReady()) { 404 | deviceCameraControl.startPreviewAsync(); 405 | mode = Mode.preview; 406 | } 407 | } 408 | } else if (mode == Mode.preview) { 409 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0.0f, 0f); 410 | batch.begin(); 411 | stage.act(); 412 | button.draw(batch, 1.0F); 413 | stage.draw(); 414 | batch.draw(texture, 0, 0, 960, 540); 415 | batch.end(); 416 | } else { 417 | /* mode = normal */ 418 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 419 | batch.begin(); 420 | stage.act(); 421 | button.draw(batch, 1.0F); 422 | stage.draw(); 423 | batch.draw(texture, 0, 0, 960, 540); 424 | batch.end(); 425 | } 426 | Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT); 427 | 428 | batch.begin(); 429 | stage.act(); 430 | button.draw(batch, 1.0F); 431 | stage.draw(); 432 | batch.draw(texture, 0, 0, 960, 540); 433 | batch.end(); 434 | 435 | Gdx.gl20.glEnable(GL20.GL_DEPTH_TEST); 436 | Gdx.gl20.glEnable(GL20.GL_TEXTURE); 437 | Gdx.gl20.glEnable(GL20.GL_TEXTURE_2D); 438 | // Gdx.gl20.glEnable(GL20.GL_LINE_SMOOTH);//54wall old 439 | Gdx.gl20.glEnable(GL20.GL_LINE_LOOP);// new 440 | Gdx.gl20.glDepthFunc(GL20.GL_LEQUAL); 441 | Gdx.gl20.glClearDepthf(1.0F); 442 | camera.update(true); 443 | // camera.apply(Gdx.gl20);//54wall old 444 | texture.bind(); 445 | for (int i = 0; i < 6; i++) { 446 | /* 447 | * 可以尝试直接使用上述代码,对一张渲染的图片进行剪切,或者使用三角形代替这里这么多的网格,然后看效果 448 | * http://blog.sina.com.cn/s/blog_940dd50a0101fl4s.html 449 | */ 450 | // mesh[i].render( GL20.GL_TRIANGLE_FAN, 0 ,4);//54wall old 451 | // ShaderProgram shader = new ShaderProgram(1 1);//原来的数目一样,不知道会不会影响 452 | // ShaderProgram shader = new ShaderProgram(String.valueOf(i), 453 | // String.valueOf(i+1));//54new 454 | // mesh[i].render(shader, GL20.GL_TRIANGLE_FAN, 0, 4);//54new 455 | } 456 | if (mode == Mode.waitForPictureReady) { 457 | /* 458 | * 注意deviceCameraControl.getPictureData()得到的是byte[],可见整体思路就是, 459 | * 将Android摄像头得到byte[],然后 460 | * 将byte[]转换为Pixmap,最后将pixmap存为jpg,这样不适用Android端图片保存模式, 461 | * byte[]----Pixmap----jpg 462 | */ 463 | if (deviceCameraControl.getPictureData() != null) { 464 | // camera picture was actually takentake Gdx Screenshot 465 | Pixmap screenshotPixmap = getScreenshot(0, 0, 466 | Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true); 467 | 468 | Pixmap cameraPixmap = new Pixmap( 469 | deviceCameraControl.getPictureData(), 0, 470 | deviceCameraControl.getPictureData().length); 471 | 472 | merge2Pixmaps(cameraPixmap, screenshotPixmap); 473 | // we could call PixmapIO.writePNG(pngfile, cameraPixmap); 474 | /* 现在有一个问题就是每次都是拍照两次,才有一张图片 */ 475 | FileHandle jpgfile = Gdx.files 476 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date 477 | + ".jpg"); 478 | Gdx.app.log("FileHandle", date); 479 | time_1 = System.currentTimeMillis(); 480 | deviceCameraControl.saveAsJpeg(jpgfile, cameraPixmap); 481 | 482 | time_2 = System.currentTimeMillis(); 483 | /* 可以得到35830ms=35s,所以非常忙,导致Mode非常缓慢的回到Mode.normal */ 484 | Gdx.app.log("cost", String.valueOf(time_2 - time_1)); 485 | deviceCameraControl.stopPreviewAsync(); 486 | /* 保存文件后,mode回到normal继续render循环,所以中间停顿的其实是卡住了?! */ 487 | mode = Mode.normal; 488 | 489 | } 490 | } 491 | /* 这个log将会一直出现 */ 492 | Gdx.app.log("mode", String.valueOf(mode)); 493 | } 494 | 495 | /* 注意截图与Android设备摄像传回的图像整合时并非按我所看的视角进行 */ 496 | private Pixmap merge2Pixmaps(Pixmap mainPixmap, Pixmap overlayedPixmap) { 497 | // merge to data and Gdx screen shot - but fix Aspect Ratio issues 498 | // between the screen and the camera 499 | Pixmap.setFilter(Filter.BiLinear); 500 | float mainPixmapAR = (float) mainPixmap.getWidth() 501 | / mainPixmap.getHeight(); 502 | float overlayedPixmapAR = (float) overlayedPixmap.getWidth() 503 | / overlayedPixmap.getHeight(); 504 | if (overlayedPixmapAR < mainPixmapAR) { 505 | int overlayNewWidth = (int) (((float) mainPixmap.getHeight() / overlayedPixmap 506 | .getHeight()) * overlayedPixmap.getWidth()); 507 | int overlayStartX = (mainPixmap.getWidth() - overlayNewWidth) / 2; 508 | // Overlaying pixmaps 509 | mainPixmap.drawPixmap(overlayedPixmap, 0, 0, 510 | overlayedPixmap.getWidth(), overlayedPixmap.getHeight(), 511 | overlayStartX, 0, overlayNewWidth, mainPixmap.getHeight()); 512 | } else { 513 | int overlayNewHeight = (int) (((float) mainPixmap.getWidth() / overlayedPixmap 514 | .getWidth()) * overlayedPixmap.getHeight()); 515 | int overlayStartY = (mainPixmap.getHeight() - overlayNewHeight) / 2; 516 | // Overlaying pixmaps 517 | mainPixmap.drawPixmap(overlayedPixmap, 0, 0, 518 | overlayedPixmap.getWidth(), overlayedPixmap.getHeight(), 0, 519 | overlayStartY, mainPixmap.getWidth(), overlayNewHeight); 520 | } 521 | return mainPixmap; 522 | } 523 | 524 | public Pixmap getScreenshot(int x, int y, int w, int h, boolean flipY) { 525 | 526 | Gdx.gl.glPixelStorei(GL20.GL_PACK_ALIGNMENT, 1); 527 | final Pixmap pixmap = new Pixmap(w, h, Format.RGBA8888); 528 | ByteBuffer pixels = pixmap.getPixels(); 529 | Gdx.gl.glReadPixels(x, y, w, h, GL20.GL_RGBA, GL20.GL_UNSIGNED_BYTE, 530 | pixels); 531 | 532 | final int numBytes = w * h * 4; 533 | byte[] lines = new byte[numBytes]; 534 | if (flipY) { 535 | final int numBytesPerLine = w * 4; 536 | for (int i = 0; i < h; i++) { 537 | pixels.position((h - i - 1) * numBytesPerLine); 538 | pixels.get(lines, i * numBytesPerLine, numBytesPerLine); 539 | } 540 | pixels.clear(); 541 | pixels.put(lines); 542 | } else { 543 | pixels.clear(); 544 | pixels.get(lines); 545 | } 546 | 547 | return pixmap; 548 | } 549 | 550 | @Override 551 | public void resize(int width, int height) { 552 | camera = new PerspectiveCamera(67.0f, 2.0f * width / height, 2.0f); 553 | camera.far = 100.0f; 554 | camera.near = 0.1f; 555 | camera.position.set(2.0f, 2.0f, 2.0f); 556 | camera.lookAt(0.0f, 0.0f, 0.0f); 557 | 558 | } 559 | 560 | @Override 561 | public void pause() { 562 | } 563 | 564 | @Override 565 | public void resume() { 566 | } 567 | 568 | ClickListener preview_on = new ClickListener() { 569 | 570 | @Override 571 | public void clicked(InputEvent event, float x, float y) { 572 | Gdx.app.log("preview_on", "preview_on按钮被点击了"); 573 | if (mode == Mode.waitForPictureReady) { 574 | mode = Mode.normal; 575 | } 576 | if (mode == Mode.normal) { 577 | mode = Mode.prepare; 578 | if (deviceCameraControl != null) { 579 | deviceCameraControl.prepareCameraAsync(); 580 | } 581 | } 582 | } 583 | 584 | }; 585 | 586 | 587 | ClickListener actor_move = new ClickListener() { 588 | 589 | @Override 590 | public void clicked(InputEvent event, float x, float y) { 591 | firstActor.setX(firstActor.getX() + 55); 592 | Gdx.app.log("actor_move", "actor_move按钮被点击了"); 593 | } 594 | 595 | }; 596 | 597 | ClickListener preview_on_1 = new ClickListener() { 598 | 599 | @Override 600 | public void clicked(InputEvent event, float x, float y) { 601 | Gdx.app.log("preview_on_1", "preview_on_1按钮被点击了"); 602 | if (mode == Mode.preview) { 603 | mode = Mode.takePicture; 604 | } 605 | 606 | } 607 | 608 | }; 609 | 610 | ClickListener preview_off = new ClickListener() { 611 | @Override 612 | public void clicked(InputEvent event, float x, float y) { 613 | Gdx.app.log("preview_on", "1按钮被点击了"); 614 | /* 615 | * 不等输入,直接写mode = 616 | * Mode.takePicture;相当于deviceCameraControl.prepareCameraAsync 617 | * ();没有写,会报空指针 java.lang.NullPointerException at 618 | * com.mygdx.game0606.android.AndroidDeviceCameraController 619 | * .takePicture(AndroidDeviceCameraController.java:122) 620 | */ 621 | 622 | /* 623 | * takePicture4render不能写在这里,因为batch.draw(texture, 0, 0, 960, 624 | * 540);应该在render中完成 625 | */ 626 | // takePicture4render(); 627 | /* 628 | * 增加下面语句后可以完成点击按钮进行拍照,关键就是让Mode进行一个完整的循环 629 | * 程序循环成Mode.normal时,屏幕再次回到黑色,才表示循环完成一次 630 | */ 631 | if (mode == Mode.waitForPictureReady) { 632 | mode = Mode.normal; 633 | } 634 | 635 | if (mode == Mode.normal) { 636 | mode = Mode.prepare; 637 | if (deviceCameraControl != null) { 638 | /* 639 | * 首先button的点击可能与Gdx.input.isTouched()输入检测有冲突,然后, 640 | * 通过仅屏蔽deviceCameraControl.prepareCameraAsync(); 641 | * 发现代码在render后 642 | * ,button依然有效,但是prepareCameraAsync后button失效,确认代码范围 643 | */ 644 | deviceCameraControl.prepareCameraAsync(); 645 | } 646 | } 647 | /* Mode.prepare之后不是Mode.preview,所以不能直接接入下边 */ 648 | // if (mode == Mode.preview) { 649 | // mode = Mode.takePicture; 650 | // } 651 | 652 | } 653 | }; 654 | 655 | } 656 | -------------------------------------------------------------------------------- /old_version/core/src/com/mygdx/game0606/actor/FirstActor.java: -------------------------------------------------------------------------------- 1 | package com.mygdx.game0606.actor; 2 | 3 | /** 4 | * @author 54wall 5 | * @date 创建时间:2016-7-21 下午1:16:58 6 | * @version 1.0 7 | */ 8 | import com.badlogic.gdx.Gdx; 9 | import com.badlogic.gdx.graphics.Texture; 10 | import com.badlogic.gdx.graphics.g2d.SpriteBatch; 11 | import com.badlogic.gdx.scenes.scene2d.Actor; 12 | 13 | public class FirstActor extends Actor { 14 | Texture texture; 15 | 16 | public void draw(SpriteBatch batch, float parentAlpha) { 17 | batch.draw(texture, this.getX(), this.getY()); 18 | } 19 | 20 | public Actor hit(float x, float y) { 21 | if (x > 0 && y > 0 && this.getHeight() > y && this.getWidth() > x) { 22 | return this; 23 | } else { 24 | return null; 25 | } 26 | } 27 | 28 | public boolean touchDown(float x, float y, int pointer) { 29 | // TODO Auto-generated method stub 30 | return false; 31 | } 32 | 33 | public void touchDragged(float x, float y, int pointer) { 34 | // TODO Auto-generated method stub 35 | } 36 | 37 | public void touchUp(float x, float y, int pointer) { 38 | // TODO Auto-generated method stub 39 | } 40 | 41 | public FirstActor(String name) { 42 | super(); 43 | texture = new Texture(Gdx.files.internal("data/james.png")); 44 | // this.height = texture.getHeight(); 45 | // this.width = texture.getWidth(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /old_version/core/src/com/mygdx/game0606/util/GetUrlImg.java: -------------------------------------------------------------------------------- 1 | package com.mygdx.game0606.util; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.net.MalformedURLException; 7 | import java.net.URL; 8 | 9 | import com.badlogic.gdx.Gdx; 10 | import com.badlogic.gdx.graphics.Pixmap; 11 | import com.badlogic.gdx.graphics.Pixmap.Format; 12 | import com.badlogic.gdx.graphics.Texture; 13 | import com.badlogic.gdx.graphics.g2d.TextureRegion; 14 | import com.badlogic.gdx.math.MathUtils; 15 | 16 | /** 17 | * @author 54wall 18 | * @date 创建时间:2016-7-21 下午3:51:09 19 | * @version 1.0 20 | * http://veikr.com/201203/libgdx_load_texture_network_async.html 21 | * libgdx中异步从网络加载图片 22 | */ 23 | public class GetUrlImg { 24 | 25 | public void getImg() throws MalformedURLException, IOException { 26 | /* 从url读取byte[] */ 27 | InputStream is = new URL("").openStream(); 28 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 29 | int length = 0; 30 | byte[] bytes = new byte[1024]; 31 | while ((length = is.read(bytes)) != -1) { 32 | out.write(bytes, 0, length); 33 | } 34 | is.close(); 35 | out.flush(); 36 | byte[] rtn = out.toByteArray(); 37 | 38 | /* 使用byte[]生成一个pixmap */ 39 | Pixmap pixmap = new Pixmap(bytes, 0, bytes.length); 40 | 41 | /* 将pixmap画到texture上 */ 42 | int width = pixmap.getWidth(); 43 | int height = pixmap.getHeight(); 44 | int preferWidth = MathUtils.nextPowerOfTwo(width); 45 | int preferHeight = MathUtils.nextPowerOfTwo(height); 46 | Texture texture = new Texture(preferWidth, preferHeight, 47 | pixmap.getFormat()); 48 | texture.draw(pixmap, 0, 0); 49 | pixmap.dispose(); 50 | /* 构造textureRegion */ 51 | TextureRegion region = new TextureRegion(texture, 0, 0, width, height); 52 | } 53 | 54 | public void name() { 55 | TextureRegion region = new TextureRegion(new Texture(1, 1, 56 | Format.RGBA8888)); 57 | loadTextureRegionFromUrl(region, "http://sss.com/asdf.png"); 58 | } 59 | 60 | public static void loadTextureRegionFromUrl(final TextureRegion region, 61 | final String url) { 62 | if (region == null) { 63 | throw new NullPointerException("region不能为空"); 64 | } 65 | new Thread() { 66 | @Override 67 | public void run() { 68 | /* 还没有新建ReaderHelper */ 69 | // final byte[] bytes = ReaderHelper.getBytesFromUrl(url); 70 | final byte[] bytes = null; 71 | System.out.println(url + " 图片获取成功:" + bytes.length); 72 | Gdx.app.postRunnable(new Runnable() { 73 | @Override 74 | public void run() { 75 | Pixmap pixmap = new Pixmap(bytes, 0, bytes.length); 76 | int width = pixmap.getWidth(); 77 | int height = pixmap.getHeight(); 78 | int preferWidth = MathUtils.nextPowerOfTwo(width); 79 | int preferHeight = MathUtils.nextPowerOfTwo(height); 80 | Texture texture = new Texture(preferWidth, 81 | preferHeight, pixmap.getFormat()); 82 | texture.draw(pixmap, 0, 0); 83 | pixmap.dispose(); 84 | region.setTexture(texture); 85 | region.setRegion(0, 0, width, height); 86 | System.out.println(region.getRegionWidth()); 87 | System.out.println(region.getRegionHeight()); 88 | System.out.println(region.getTexture().getHeight()); 89 | } 90 | }); 91 | }; 92 | }.start(); 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /old_version/ver_2016.7.21.11.18/Android/src/com/mygdx/game0606/android/AndroidDeviceCameraController.java: -------------------------------------------------------------------------------- 1 | package com.mygdx.game0606.android; 2 | 3 | /** 4 | * @author 54wall 5 | * @date 创建时间:2016-7-14 上午11:45:41 6 | * @version 1.0 7 | */ 8 | import java.io.BufferedOutputStream; 9 | import java.io.File; 10 | import java.io.FileNotFoundException; 11 | import java.io.FileOutputStream; 12 | import java.io.IOException; 13 | import java.util.List; 14 | import com.badlogic.gdx.files.FileHandle; 15 | import com.badlogic.gdx.graphics.Pixmap; 16 | import com.mygdx.game0606.DeviceCameraControl; 17 | 18 | 19 | import android.content.Context; 20 | import android.graphics.Bitmap; 21 | import android.graphics.Bitmap.CompressFormat; 22 | import android.hardware.Camera; 23 | import android.hardware.Camera.PictureCallback; 24 | import android.hardware.Camera.ShutterCallback; 25 | import android.os.Environment; 26 | import android.text.Layout; 27 | import android.view.Gravity; 28 | import android.view.ViewGroup; 29 | import android.view.ViewParent; 30 | import android.view.ViewGroup.LayoutParams; 31 | import android.widget.Button; 32 | import android.widget.FrameLayout; 33 | import android.widget.RelativeLayout; 34 | import android.widget.Toast; 35 | 36 | public class AndroidDeviceCameraController implements DeviceCameraControl, 37 | Camera.PictureCallback, Camera.AutoFocusCallback { 38 | 39 | private static final int ONE_SECOND_IN_MILI = 1000; 40 | private final AndroidLauncher activity; 41 | private CameraSurface cameraSurface; 42 | private byte[] pictureData; 43 | private Context context; 44 | 45 | public AndroidDeviceCameraController(AndroidLauncher activity) { 46 | this.activity = activity; 47 | } 48 | 49 | @Override 50 | public synchronized void prepareCamera() { 51 | // activity.setFixedSize(960, 640);//new 52 | // activity.setFixedSize(480, 320);//54wall 53 | if (cameraSurface == null) { 54 | cameraSurface = new CameraSurface(activity); 55 | } 56 | /*可以控制摄像头预览窗口大小*/ 57 | // activity.addContentView(cameraSurface, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); 58 | /*activity.addContentView只能有一个否则报错: 59 | * java.lang.IllegalStateException: The specified child already has a parent. 60 | * You must call removeView() on the child's parent first. 61 | * 这也是在core代码中libgdx只能在render中调用AndroidDeviceCameraController中开启相机的原因*/ 62 | // activity.addContentView(cameraSurface, new LayoutParams(960, 640)); 63 | /*http://blog.csdn.net/drrlalala/article/details/38332017*/ 64 | FrameLayout.LayoutParams params = new FrameLayout.LayoutParams 65 | (680,680); 66 | //设置顶部,左边布局 67 | // params.gravity=Gravity.CENTER_HORIZONTAL|Gravity.RIGHT; 68 | // params.gravity=Gravity.LEFT|Gravity.RIGHT; 69 | params.rightMargin=150;//可以通过设置rightMargin控制组件的实际位置 70 | params.leftMargin=200;//可以通过设置rightMargin控制组件的实际位置 71 | params.topMargin=100; 72 | activity.addContentView(cameraSurface, params); 73 | 74 | 75 | } 76 | 77 | @Override 78 | public synchronized void startPreview() { 79 | // ...and start previewing. From now on, the camera keeps pushing preview images to the surface. 80 | if (cameraSurface != null && cameraSurface.getCamera() != null) { 81 | cameraSurface.getCamera().startPreview(); 82 | } 83 | } 84 | 85 | @Override 86 | public synchronized void stopPreview() { 87 | // stop previewing. 88 | if (cameraSurface != null) { 89 | ViewParent parentView = cameraSurface.getParent(); 90 | if (parentView instanceof ViewGroup) { 91 | ViewGroup viewGroup = (ViewGroup) parentView; 92 | viewGroup.removeView(cameraSurface); 93 | } 94 | if (cameraSurface.getCamera() != null) { 95 | cameraSurface.getCamera().stopPreview(); 96 | } 97 | } 98 | activity.restoreFixedSize(); 99 | } 100 | 101 | public void setCameraParametersForPicture(Camera camera) { 102 | // Before we take the picture - we make sure all camera parameters are 103 | // as we like them 104 | // Use max resolution and auto focus 105 | Camera.Parameters p = camera.getParameters(); 106 | List supportedSizes = p.getSupportedPictureSizes(); 107 | int maxSupportedWidth = -1; 108 | int maxSupportedHeight = -1; 109 | for (Camera.Size size : supportedSizes) { 110 | if (size.width > maxSupportedWidth) { 111 | maxSupportedWidth = size.width; 112 | maxSupportedHeight = size.height; 113 | } 114 | } 115 | p.setPictureSize(maxSupportedWidth, maxSupportedHeight); 116 | p.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); 117 | camera.setParameters(p); 118 | } 119 | 120 | @Override 121 | public synchronized void takePicture() { 122 | // the user request to take a picture - start the process by requesting 123 | // focus 124 | setCameraParametersForPicture(cameraSurface.getCamera()); 125 | cameraSurface.getCamera().autoFocus(this); 126 | } 127 | 128 | @Override 129 | public synchronized void onAutoFocus(boolean success, Camera camera) { 130 | // Focus process finished, we now have focus (or not) 131 | if (success) { 132 | if (camera != null) { 133 | camera.stopPreview(); 134 | /*android6.0下边都是不推荐的了,具体找下相应替代语句*/ 135 | // camera.takePicture(null, null, null, this);//old 136 | // camera.takePicture(null, null, null);//54wall 137 | /*增加三个回调函数后,可以进行拍照,并且成功保存*/ 138 | // We now have focus take the actual picture 139 | camera.takePicture(shutterCallback, rawPictureCallback, jpegPictureCallback);//54wall 140 | /*54wall:末尾增加重新开始预览就可以继续预览图像了:http://www.xuebuyuan.com/1982434.html */ 141 | camera.startPreview(); 142 | 143 | } 144 | } 145 | } 146 | 147 | 148 | 149 | 150 | ShutterCallback shutterCallback = new ShutterCallback() { 151 | @Override 152 | public void onShutter() { 153 | } 154 | }; 155 | 156 | PictureCallback rawPictureCallback = new PictureCallback() { 157 | @Override 158 | public void onPictureTaken(byte[] arg0, Camera arg1) { 159 | 160 | } 161 | }; 162 | 163 | PictureCallback jpegPictureCallback = new PictureCallback() { 164 | @Override 165 | public void onPictureTaken(byte[] arg0, Camera arg1) { 166 | /*可以在Android项目中中生成图片*/ 167 | // String fileName = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) 168 | // .toString() 169 | // + File.separator 170 | // + "PicTest_" + System.currentTimeMillis() + ".jpg"; 171 | // File file = new File(fileName); 172 | // if (!file.getParentFile().exists()) { 173 | // file.getParentFile().mkdir(); 174 | // } 175 | // 176 | // try { 177 | // BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file)); 178 | // bos.write(arg0); 179 | // bos.flush(); 180 | // bos.close(); 181 | // 182 | // } catch (Exception e) { 183 | // 184 | // } 185 | /*54wall:因为在libgdx合成图像时,发现pictureData=null*/ 186 | pictureData=arg0; 187 | 188 | }; 189 | }; 190 | 191 | @Override 192 | public synchronized void onPictureTaken(byte[] pictureData, Camera camera) { 193 | // We got the picture data - keep it 194 | this.pictureData = pictureData; 195 | } 196 | 197 | @Override 198 | public synchronized byte[] getPictureData() { 199 | // Give to picture data to whom ever requested it 200 | return pictureData; 201 | } 202 | 203 | @Override 204 | public void prepareCameraAsync() { 205 | Runnable r = new Runnable() { 206 | public void run() { 207 | prepareCamera(); 208 | } 209 | }; 210 | activity.post(r); 211 | } 212 | 213 | @Override 214 | public synchronized void startPreviewAsync() { 215 | Runnable r = new Runnable() { 216 | public void run() { 217 | startPreview(); 218 | } 219 | }; 220 | activity.post(r); 221 | } 222 | 223 | @Override 224 | public synchronized void stopPreviewAsync() { 225 | Runnable r = new Runnable() { 226 | public void run() { 227 | stopPreview(); 228 | } 229 | }; 230 | activity.post(r); 231 | } 232 | 233 | @Override 234 | public synchronized byte[] takePictureAsync(long timeout) { 235 | timeout *= ONE_SECOND_IN_MILI; 236 | /*pictureData会报错*/ 237 | // pictureData = null;//old 238 | Runnable r = new Runnable() { 239 | public void run() { 240 | takePicture(); 241 | } 242 | }; 243 | activity.post(r); 244 | while (pictureData == null && timeout > 0) { 245 | try { 246 | Thread.sleep(ONE_SECOND_IN_MILI); 247 | timeout -= ONE_SECOND_IN_MILI; 248 | } catch (InterruptedException e) { 249 | // TODO Auto-generated catch block 250 | e.printStackTrace(); 251 | } 252 | } 253 | if (pictureData == null) { 254 | cameraSurface.getCamera().cancelAutoFocus(); 255 | } 256 | return pictureData; 257 | } 258 | 259 | 260 | 261 | /*在LibGDX中,图片以pixmap为存在格式,所以Android与LibGDX进行交互,必须有saveAsJpeg*/ 262 | @Override 263 | public void saveAsJpeg(FileHandle jpgfile, Pixmap pixmap) { 264 | FileOutputStream fos; 265 | int x = 0, y = 0; 266 | int xl = 0, yl = 0; 267 | try { 268 | Bitmap bmp = Bitmap.createBitmap(pixmap.getWidth(), 269 | pixmap.getHeight(), Bitmap.Config.ARGB_8888); 270 | // we need to switch between LibGDX RGBA format to Android ARGB 271 | // format 272 | for (x = 0, xl = pixmap.getWidth(); x < xl; x++) { 273 | for (y = 0, yl = pixmap.getHeight(); y < yl; y++) { 274 | int color = pixmap.getPixel(x, y); 275 | // RGBA => ARGB 276 | int RGB = color >> 8; 277 | int A = (color & 0x000000ff) << 24; 278 | int ARGB = A | RGB; 279 | bmp.setPixel(x, y, ARGB); 280 | } 281 | } 282 | fos = new FileOutputStream(jpgfile.file()); 283 | bmp.compress(CompressFormat.JPEG, 90, fos); 284 | fos.close(); 285 | } catch (FileNotFoundException e) { 286 | e.printStackTrace(); 287 | } catch (IOException e) { 288 | e.printStackTrace(); 289 | } catch (IllegalArgumentException e) { 290 | e.printStackTrace(); 291 | } 292 | } 293 | 294 | @Override 295 | public boolean isReady() { 296 | if (cameraSurface != null && cameraSurface.getCamera() != null) { 297 | return true; 298 | } 299 | return false; 300 | } 301 | } 302 | -------------------------------------------------------------------------------- /old_version/ver_2016.7.21.11.18/Android/src/com/mygdx/game0606/android/AndroidLauncher.java: -------------------------------------------------------------------------------- 1 | package com.mygdx.game0606.android; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.badlogic.gdx.backends.android.AndroidApplication; 6 | import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration; 7 | import com.mygdx.game0606.DeviceCameraControl; 8 | import com.mygdx.game0606.MyGdxGame0606; 9 | 10 | import android.content.pm.ActivityInfo; 11 | import android.graphics.PixelFormat; 12 | import android.view.SurfaceView; 13 | 14 | public class AndroidLauncher extends AndroidApplication { 15 | private int origWidth; 16 | private int origHeight; 17 | @Override 18 | public void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | //强制竖屏 21 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//通过程序改变屏 22 | AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration(); 23 | //OpenGL ES 1.x support removed from libgdx(http://www.badlogicgames.com/wordpress/?p=3311) 24 | // cfg.useGL20 = false;//54wall old 25 | // we need to change the default pixel format - since it does not 26 | // include an alpha channel 27 | // we need the alpha channel so the camera preview will be seen behind 28 | // the GL scene 29 | cfg.r = 8; 30 | cfg.g = 8; 31 | cfg.b = 8; 32 | cfg.a = 8; 33 | DeviceCameraControl cameraControl = new AndroidDeviceCameraController( 34 | this); 35 | //拍照程序在AndroidDeviceCameraController,通过cameraControl传给MyGdxGame0606,进入LibGDX 36 | initialize(new MyGdxGame0606(cameraControl), cfg); 37 | 38 | if (graphics.getView() instanceof SurfaceView) { 39 | SurfaceView glView = (SurfaceView) graphics.getView(); 40 | // force alpha channel - I'm not sure we need this as the GL surface 41 | // is already using alpha channel 42 | glView.getHolder().setFormat(PixelFormat.TRANSLUCENT); 43 | } 44 | // we don't want the screen to turn off during the long image saving 45 | // process 46 | graphics.getView().setKeepScreenOn(true); 47 | // keep the original screen size 48 | origWidth = graphics.getWidth(); 49 | origHeight = graphics.getHeight(); 50 | } 51 | 52 | public void post(Runnable r) { 53 | handler.post(r); 54 | } 55 | 56 | public void setFixedSize(int width, int height) { 57 | if (graphics.getView() instanceof SurfaceView) { 58 | SurfaceView glView = (SurfaceView) graphics.getView(); 59 | glView.getHolder().setFormat(PixelFormat.TRANSLUCENT); 60 | glView.getHolder().setFixedSize(width, height); 61 | } 62 | } 63 | 64 | public void restoreFixedSize() { 65 | if (graphics.getView() instanceof SurfaceView) { 66 | SurfaceView glView = (SurfaceView) graphics.getView(); 67 | glView.getHolder().setFormat(PixelFormat.TRANSLUCENT); 68 | glView.getHolder().setFixedSize(origWidth, origHeight); 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /old_version/ver_2016.7.21.11.18/Android/src/com/mygdx/game0606/android/CameraSurface.java: -------------------------------------------------------------------------------- 1 | package com.mygdx.game0606.android; 2 | 3 | /** 4 | * @author 54wall 5 | * @date 创建时间:2016-7-14 上午11:44:40 6 | * @version 1.0 7 | */ 8 | 9 | import java.io.IOException; 10 | import android.content.Context; 11 | import android.hardware.Camera; 12 | import android.os.Build; 13 | import android.view.SurfaceHolder; 14 | import android.view.SurfaceView; 15 | 16 | public class CameraSurface extends SurfaceView implements 17 | SurfaceHolder.Callback { 18 | private Camera camera; 19 | 20 | public CameraSurface(Context context) { 21 | super(context); 22 | // We're implementing the Callback interface and want to get notified 23 | // about certain surface events. 24 | getHolder().addCallback(this); 25 | // We're changing the surface to a PUSH surface, meaning we're receiving 26 | // all buffer data from another component - the camera, in this case. 27 | getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 28 | } 29 | public void surfaceCreated(SurfaceHolder holder) { 30 | // Once the surface is created, simply open a handle to the camera 31 | // hardware. 32 | // camera = Camera.open(); 33 | camera = Camera.open(0); 34 | camera.setDisplayOrientation(90); 35 | } 36 | 37 | public void surfaceChanged(SurfaceHolder holder, int format, int width, 38 | int height) { 39 | // This method is called when the surface changes, e.g. when it's size 40 | // is set. 41 | // We use the opportunity to initialize the camera preview display 42 | // dimensions. 43 | Camera.Parameters p = camera.getParameters(); 44 | // p.setPreviewSize(width, height);//old 会报 setParameters failed 45 | camera.setParameters(p); 46 | 47 | // We also assign the preview display to this surface... 48 | try { 49 | camera.setPreviewDisplay(holder); 50 | } catch (IOException e) { 51 | e.printStackTrace(); 52 | } 53 | } 54 | 55 | public void surfaceDestroyed(SurfaceHolder holder) { 56 | // Once the surface gets destroyed, we stop the preview mode and release 57 | // the whole camera since we no longer need it. 58 | camera.stopPreview(); 59 | camera.release(); 60 | camera = null; 61 | } 62 | 63 | public Camera getCamera() { 64 | return camera; 65 | } 66 | 67 | } -------------------------------------------------------------------------------- /old_version/ver_2016.7.21.11.18/README.md: -------------------------------------------------------------------------------- 1 | 实现两个按键,按下1,进行预览,按下2,进行聚焦拍摄 -------------------------------------------------------------------------------- /old_version/ver_2016.7.21.11.18/core/src/MyGdxGame0606.gwt.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /old_version/ver_2016.7.21.11.18/core/src/com/mygdx/game0606/Constant.java: -------------------------------------------------------------------------------- 1 | package com.mygdx.game0606; 2 | 3 | import com.badlogic.gdx.graphics.Color; 4 | 5 | /** 6 | * @author 54wall 7 | * @date 创建时间:2016-7-19 下午3:18:21 8 | * @version 1.0 9 | */ 10 | public class Constant { 11 | 12 | public static final float vertexData[] = { 13 | 1.0f, 14 | 1.0f, 15 | 1.0f, 16 | Color.toFloatBits(255, 255, 255, 255), 17 | 0.0f, 18 | 0.0f, // quad/face 0/Vertex 0 19 | 0.0f, 20 | 1.0f, 21 | 1.0f, 22 | Color.toFloatBits(255, 255, 255, 255), 23 | 0.0f, 24 | 1.0f, // quad/face 0/Vertex 1 25 | 0.0f, 26 | 0.0f, 27 | 1.0f, 28 | Color.toFloatBits(255, 255, 255, 255), 29 | 1.0f, 30 | 1.0f, // quad/face 0/Vertex 2 31 | 1.0f, 32 | 0.0f, 33 | 1.0f, 34 | Color.toFloatBits(255, 255, 255, 255), 35 | 1.0f, 36 | 0.0f, // quad/face 0/Vertex 3 37 | 38 | 1.0f, 39 | 1.0f, 40 | 1.0f, 41 | Color.toFloatBits(255, 255, 255, 255), 42 | 1.0f, 43 | 1.0f, // quad/face 1/Vertex 4 44 | 1.0f, 45 | 0.0f, 46 | 1.0f, 47 | Color.toFloatBits(255, 255, 255, 255), 48 | 0.0f, 49 | 1.0f, // quad/face 1/Vertex 5 50 | 1.0f, 51 | 0.0f, 52 | 0.0f, 53 | Color.toFloatBits(255, 255, 255, 255), 54 | 0.0f, 55 | 0.0f, // quad/face 1/Vertex 6 56 | 1.0f, 57 | 1.0f, 58 | 0.0f, 59 | Color.toFloatBits(255, 255, 255, 255), 60 | 1.0f, 61 | 0.0f, // quad/face 1/Vertex 7 62 | 63 | 1.0f, 64 | 1.0f, 65 | 1.0f, 66 | Color.toFloatBits(255, 255, 255, 255), 67 | 0.0f, 68 | 0.0f, // quad/face 2/Vertex 8 69 | 1.0f, 70 | 1.0f, 71 | 0.0f, 72 | Color.toFloatBits(255, 255, 255, 255), 73 | 0.0f, 74 | 1.0f, // quad/face 2/Vertex 9 75 | 0.0f, 76 | 1.0f, 77 | 0.0f, 78 | Color.toFloatBits(255, 255, 255, 255), 79 | 1.0f, 80 | 1.0f, // quad/face 2/Vertex 10 81 | 0.0f, 82 | 1.0f, 83 | 1.0f, 84 | Color.toFloatBits(255, 255, 255, 255), 85 | 1.0f, 86 | 0.0f, // quad/face 2/Vertex 11 87 | 88 | 1.0f, 89 | 0.0f, 90 | 0.0f, 91 | Color.toFloatBits(255, 255, 255, 255), 92 | 1.0f, 93 | 1.0f, // quad/face 3/Vertex 12 94 | 0.0f, 95 | 0.0f, 96 | 0.0f, 97 | Color.toFloatBits(255, 255, 255, 255), 98 | 0.0f, 99 | 1.0f, // quad/face 3/Vertex 13 100 | 0.0f, 101 | 1.0f, 102 | 0.0f, 103 | Color.toFloatBits(255, 255, 255, 255), 104 | 0.0f, 105 | 0.0f, // quad/face 3/Vertex 14 106 | 1.0f, 107 | 1.0f, 108 | 0.0f, 109 | Color.toFloatBits(255, 255, 255, 255), 110 | 1.0f, 111 | 0.0f, // quad/face 3/Vertex 15 112 | 113 | 0.0f, 114 | 1.0f, 115 | 1.0f, 116 | Color.toFloatBits(255, 255, 255, 255), 117 | 1.0f, 118 | 1.0f, // quad/face 4/Vertex 16 119 | 0.0f, 120 | 1.0f, 121 | 0.0f, 122 | Color.toFloatBits(255, 255, 255, 255), 123 | 0.0f, 124 | 1.0f, // quad/face 4/Vertex 17 125 | 0.0f, 126 | 0.0f, 127 | 0.0f, 128 | Color.toFloatBits(255, 255, 255, 255), 129 | 0.0f, 130 | 0.0f, // quad/face 4/Vertex 18 131 | 0.0f, 132 | 0.0f, 133 | 1.0f, 134 | Color.toFloatBits(255, 255, 255, 255), 135 | 1.0f, 136 | 0.0f, // quad/face 4/Vertex 19 137 | 138 | 0.0f, 0.0f, 139 | 0.0f, 140 | Color.toFloatBits(255, 255, 255, 255), 141 | 1.0f, 142 | 1.0f, // quad/face 5/Vertex 20 143 | 1.0f, 0.0f, 0.0f, 144 | Color.toFloatBits(255, 255, 255, 255), 145 | 0.0f, 146 | 1.0f, // quad/face 5/Vertex 21 147 | 1.0f, 0.0f, 1.0f, Color.toFloatBits(255, 255, 255, 255), 148 | 0.0f, 149 | 0.0f, // quad/face 5/Vertex 22 150 | 0.0f, 0.0f, 1.0f, Color.toFloatBits(255, 255, 255, 255), 1.0f, 151 | 0.0f, // quad/face 5/Vertex 23 152 | }; 153 | } 154 | -------------------------------------------------------------------------------- /old_version/ver_2016.7.21.11.18/core/src/com/mygdx/game0606/DeviceCameraControl.java: -------------------------------------------------------------------------------- 1 | package com.mygdx.game0606; 2 | 3 | import com.badlogic.gdx.files.FileHandle; 4 | import com.badlogic.gdx.graphics.Pixmap; 5 | 6 | /** 7 | * @author 54wall 8 | * @date 创建时间:2016-7-14 下午12:38:29 9 | * @version 1.0 10 | */ 11 | public interface DeviceCameraControl { 12 | 13 | // Synchronous interface 14 | void prepareCamera(); 15 | 16 | void startPreview(); 17 | 18 | void stopPreview(); 19 | 20 | void takePicture(); 21 | 22 | byte[] getPictureData(); 23 | 24 | // Asynchronous interface - need when called from a non platform thread (GDX 25 | // OpenGl thread) 26 | void startPreviewAsync(); 27 | 28 | void stopPreviewAsync(); 29 | 30 | byte[] takePictureAsync(long timeout); 31 | 32 | void saveAsJpeg(FileHandle jpgfile, Pixmap cameraPixmap); 33 | 34 | boolean isReady(); 35 | 36 | void prepareCameraAsync(); 37 | } -------------------------------------------------------------------------------- /old_version/ver_2016.7.21.11.18/core/src/com/mygdx/game0606/MyGdxGame0606.java: -------------------------------------------------------------------------------- 1 | package com.mygdx.game0606; 2 | 3 | import java.nio.ByteBuffer; 4 | import java.text.SimpleDateFormat; 5 | 6 | import com.badlogic.gdx.Application; 7 | import com.badlogic.gdx.ApplicationListener; 8 | import com.badlogic.gdx.Gdx; 9 | import com.badlogic.gdx.files.FileHandle; 10 | import com.badlogic.gdx.graphics.Color; 11 | import com.badlogic.gdx.graphics.GL20;//oldGL20 12 | import com.badlogic.gdx.graphics.Mesh; 13 | import com.badlogic.gdx.graphics.PerspectiveCamera; 14 | import com.badlogic.gdx.graphics.Pixmap; 15 | import com.badlogic.gdx.graphics.Texture; 16 | import com.badlogic.gdx.graphics.Texture.TextureFilter; 17 | import com.badlogic.gdx.graphics.VertexAttribute; 18 | import com.badlogic.gdx.graphics.Pixmap.Filter; 19 | import com.badlogic.gdx.graphics.Pixmap.Format; 20 | import com.badlogic.gdx.graphics.VertexAttributes.Usage; 21 | import com.badlogic.gdx.graphics.g2d.BitmapFont; 22 | import com.badlogic.gdx.graphics.g2d.SpriteBatch; 23 | import com.badlogic.gdx.graphics.g2d.TextureRegion; 24 | import com.badlogic.gdx.graphics.glutils.ShaderProgram; 25 | import com.badlogic.gdx.scenes.scene2d.Actor; 26 | import com.badlogic.gdx.scenes.scene2d.InputEvent; 27 | import com.badlogic.gdx.scenes.scene2d.Stage; 28 | import com.badlogic.gdx.scenes.scene2d.ui.Button; 29 | import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; 30 | import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; 31 | import com.badlogic.gdx.utils.viewport.StretchViewport; 32 | import com.mygdx.game0606.actor.FirstActor; 33 | 34 | public class MyGdxGame0606 implements ApplicationListener { 35 | /* http://blog.csdn.net/xietansheng/article/details/50187861 */ 36 | private Stage stage;// 舞台 37 | private Texture actorTexture; 38 | private Texture move_1_Texture; 39 | private Texture move_2_Texture; 40 | private Texture upTexture; 41 | private Texture downTexture; 42 | private Button button;// 按钮 43 | private Button button_1;// 按钮 44 | private Button button_move;// 按钮 45 | // 视口世界的宽高统使用 480 * 800, 并统一使用伸展视口(StretchViewport) 46 | public static final float WORLD_WIDTH = 800; 47 | public static final float WORLD_HEIGHT = 600; 48 | /* 54wall */ 49 | public SpriteBatch batch; 50 | public Texture texture_demo; 51 | private SimpleDateFormat sDateFormat = new SimpleDateFormat( 52 | "yyyy-MM-dd hh:mm:ss"); 53 | private String date = sDateFormat.format(new java.util.Date()); 54 | 55 | public enum Mode { 56 | normal, prepare, preview, takePicture, waitForPictureReady, 57 | } 58 | 59 | public int state_normal = 0; 60 | public int state_prepare = 1; 61 | 62 | public Constant constant = new Constant(); 63 | 64 | public static final short facesVerticesIndex[][] = { { 0, 1, 2, 3 }, 65 | { 4, 5, 6, 7 }, { 8, 9, 10, 11 }, { 12, 13, 14, 15 }, 66 | { 16, 17, 18, 19 }, { 20, 21, 22, 23 } }; 67 | 68 | private final static VertexAttribute verticesAttributes[] = new VertexAttribute[] { 69 | new VertexAttribute(Usage.Position, 3, "a_position"), 70 | new VertexAttribute(Usage.ColorPacked, 4, "a_color"), 71 | new VertexAttribute(Usage.TextureCoordinates, 2, "a_texCoords"), }; 72 | 73 | private Texture texture; 74 | 75 | private Mesh[] mesh = new Mesh[6]; 76 | 77 | private PerspectiveCamera camera; 78 | 79 | private Mode mode = Mode.normal; 80 | 81 | private final DeviceCameraControl deviceCameraControl; 82 | private long time_1; 83 | private long time_2; 84 | private int i_render = 0; 85 | 86 | private Actor firstActor; 87 | 88 | /* 89 | * 通过this.deviceCameraControl= 90 | * cameraControl获取Android端摄像头然后后续所有的deviceCameraControl实际调用的都是Android的东西 91 | */ 92 | public MyGdxGame0606(DeviceCameraControl cameraControl) { 93 | this.deviceCameraControl = cameraControl; 94 | } 95 | 96 | @Override 97 | public void create() { 98 | /* http://blog.csdn.net/xietansheng/article/details/50187861 */ 99 | // 设置日志输出级别 100 | Gdx.app.setLogLevel(Application.LOG_DEBUG); 101 | // 使用伸展视口(StretchViewport)创建舞台 102 | stage = new Stage(new StretchViewport(WORLD_WIDTH, WORLD_HEIGHT)); 103 | // 将输入处理设置到舞台(必须设置, 否则点击按钮没效果) 104 | Gdx.input.setInputProcessor(stage); 105 | firstActor = new Actor(); 106 | firstActor.setPosition(100, 300); 107 | 108 | /* 第 1 步: 创建 弹起 和 按下 两种状态的纹理 */ 109 | 110 | move_1_Texture = new Texture(Gdx.files.internal("data/move_0.png")); 111 | move_2_Texture = new Texture(Gdx.files.internal("data/move_1.png")); 112 | actorTexture = new Texture(Gdx.files.internal("data/james.png")); 113 | upTexture = new Texture(Gdx.files.internal("data/button_1.png")); 114 | downTexture = new Texture(Gdx.files.internal("data/button_2.png")); 115 | /* 第 2 步: 创建 ButtonStyle */ 116 | Button.ButtonStyle style_move = new Button.ButtonStyle(); 117 | Button.ButtonStyle style = new Button.ButtonStyle(); 118 | // 设置 style 的 弹起 和 按下 状态的纹理区域 119 | style_move.up=new TextureRegionDrawable(new TextureRegion(move_1_Texture)); 120 | style_move.down=new TextureRegionDrawable(new TextureRegion(move_2_Texture)); 121 | 122 | style.up = new TextureRegionDrawable(new TextureRegion(upTexture)); 123 | style.down = new TextureRegionDrawable(new TextureRegion(downTexture)); 124 | /* 第 3 步: 创建 Button */ 125 | 126 | button_move = new Button(style_move); 127 | // 设置按钮的位置 128 | button_move.setPosition(100, 350); 129 | // 给按钮添加点击监听器 130 | button_move.addListener(actor_move); 131 | 132 | 133 | 134 | button = new Button(style); 135 | // 设置按钮的位置 136 | button.setPosition(100, 300); 137 | // 给按钮添加点击监听器 138 | button.addListener(preview_on); 139 | 140 | button_1 = new Button(style); 141 | // 设置按钮的位置 142 | button_1.setPosition(550, 400); 143 | // 给按钮添加点击监听器 144 | button_1.addListener(preview_on_1); 145 | 146 | /* 第 4 步: 添加 button 到舞台 */ 147 | stage.addActor(button); 148 | stage.addActor(button_1); 149 | stage.addActor(button_move); 150 | stage.addActor(firstActor); 151 | 152 | /* 54wall */ 153 | batch = new SpriteBatch(); 154 | texture_demo = new Texture(Gdx.files.internal("data/1.png")); 155 | // Load the Libgdx splash screen texture 156 | texture = new Texture(Gdx.files.internal("data/libgdx.png")); 157 | texture.setFilter(TextureFilter.Linear, TextureFilter.Linear); 158 | 159 | // Create the 6 faces of the Cube 160 | for (int i = 0; i < 6; i++) { 161 | mesh[i] = new Mesh(true, 24, 4, verticesAttributes); 162 | mesh[i].setVertices(Constant.vertexData); 163 | mesh[i].setIndices(facesVerticesIndex[i]); 164 | } 165 | 166 | // Create the OpenGL Camera,这里指的是视角,正交视角与设备摄像头完全不是一个东西 167 | camera = new PerspectiveCamera(67.0f, 2.0f * Gdx.graphics.getWidth() 168 | / Gdx.graphics.getHeight(), 2.0f);// oldfloat 169 | // fieldOfViewY改为37无反应 170 | camera.far = 100.0f;// old 改为50,无反应 171 | 172 | camera.near = 0.1f; 173 | camera.position.set(2.0f, 2.0f, 2.0f); 174 | camera.lookAt(0.0f, 0.0f, 0.0f);// old 175 | 176 | } 177 | 178 | /* 手动释放资源 */ 179 | @Override 180 | public void dispose() { 181 | /* 对应button,应用退出时释放资源 */ 182 | if (upTexture != null) { 183 | upTexture.dispose(); 184 | } 185 | if (downTexture != null) { 186 | downTexture.dispose(); 187 | } 188 | if (stage != null) { 189 | stage.dispose(); 190 | } 191 | /* 54wall */ 192 | batch.dispose(); 193 | texture_demo.dispose(); 194 | 195 | texture.dispose(); 196 | for (int i = 0; i < 6; i++) { 197 | mesh[i].dispose(); 198 | mesh[i] = null; 199 | } 200 | texture = null; 201 | } 202 | 203 | /* 通过debug发现,每次点击运行(断点在render内)render都会一直运行,可见render作为渲染的一个覆盖函数的确是处于一直运行的状态 */ 204 | @Override 205 | public void render() { 206 | /*如何控制render一进入就使Android相机进入preview,直接在render加入50 100计数器,保证在50之前为mode的一个状态,随着render的进行 207 | * 计数器进行计数,然后每次只执行一次deviceCameraControl,就可以直接进入相机的预览模式*/ 208 | // Gdx.gl20.glClearColor(0.0f, 0f, 0.0f, 0.0f);//黑 209 | // Gdx.gl.glClearColor(1, 1, 1, 1);// 设置背景为白色 210 | Gdx.gl.glClearColor(0.57f, 0.40f, 0.55f, 1.0f);// 紫色 211 | Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);// 清屏 212 | render_preview(); 213 | 214 | } 215 | 216 | /* 217 | * 1 发现在打开摄像头后,button全部失效,只有没有camera预览时,button才有效,是不是渲染时摄像头与绘制的button存在冲突 218 | * 并且在调试button时,屏幕处于按压状态也是和button冲突了 219 | * 220 | * 2 221 | * 现在实现的功能是按下左按钮,开始预览,按下右侧按钮进行聚焦拍摄,这说明在mode为preview状态时,button是可以相应的之前却一直不可以 222 | */ 223 | public void render_preview() { 224 | /* 我已经将preview变为takePicture状态移动到click中,实现先预览再拍照 */ 225 | Gdx.gl20.glHint(GL20.GL_GENERATE_MIPMAP_HINT, GL20.GL_NICEST); 226 | if (mode == Mode.takePicture) { 227 | /* 没有清屏,摄像头的预览功能就没有,演员和舞台在各个if中可以不加 */ 228 | Gdx.gl20.glClearColor(0f, 0.0f, 0.0f, 0.0f); 229 | if (deviceCameraControl != null) { 230 | deviceCameraControl.takePicture(); 231 | } 232 | mode = Mode.waitForPictureReady; 233 | } else if (mode == Mode.waitForPictureReady) { 234 | Gdx.gl20.glClearColor(0.0f, 0f, 0.0f, 0.0f); 235 | } else if (mode == Mode.prepare) { 236 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0f, 0.6f); 237 | if (deviceCameraControl != null) { 238 | if (deviceCameraControl.isReady()) { 239 | deviceCameraControl.startPreviewAsync(); 240 | mode = Mode.preview; 241 | } 242 | } 243 | } else if (mode == Mode.preview) { 244 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0.0f, 0f); 245 | } else { 246 | /* mode = normal */ 247 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0.6f, 1.0f); 248 | 249 | } 250 | Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT); 251 | /* 下边放到texture.bind();时效果一致 */ 252 | batch.begin(); 253 | 254 | stage.act(); // 更新舞台逻辑 255 | /* 新增演员 ,放到这里才会显示*/ 256 | // batch.draw(actorTexture, 100, 300);//这么写,每次的移动无效,因为render画的动作被写死了 257 | batch.draw(actorTexture, firstActor.getX(), firstActor.getY()); 258 | batch.draw(texture, 480, 480, texture.getWidth(), texture.getHeight()); 259 | button.draw(batch, 1.0F);// 仅绘制actor 260 | button_1.draw(batch, 1.0F); 261 | button_move.draw(batch, 1.0f); 262 | /* 新增演员 ,放到这里不会显示*/ 263 | // batch.draw(actorTexture, 100, 300); 264 | 265 | stage.draw();// 绘制舞台 266 | // batch.draw(texture, 0, 0, 960, 540); 267 | batch.end(); 268 | 269 | Gdx.gl20.glEnable(GL20.GL_DEPTH_TEST); 270 | Gdx.gl20.glEnable(GL20.GL_TEXTURE); 271 | Gdx.gl20.glEnable(GL20.GL_TEXTURE_2D); 272 | // Gdx.gl20.glEnable(GL20.GL_LINE_SMOOTH);//54wall old 273 | Gdx.gl20.glEnable(GL20.GL_LINE_LOOP);// new 274 | Gdx.gl20.glDepthFunc(GL20.GL_LEQUAL); 275 | Gdx.gl20.glClearDepthf(1.0F); 276 | camera.update(true); 277 | // camera.apply(Gdx.gl20);//54wall old 278 | texture.bind(); 279 | 280 | if (mode == Mode.waitForPictureReady) { 281 | /* 282 | * 注意deviceCameraControl.getPictureData()得到的是byte[],可见整体思路就是, 283 | * 将Android摄像头得到byte[],然后 284 | * 将byte[]转换为Pixmap,最后将pixmap存为jpg,这样不适用Android端图片保存模式, 285 | * byte[]----Pixmap----jpg 286 | */ 287 | if (deviceCameraControl.getPictureData() != null) { 288 | // camera picture was actually takentake Gdx Screenshot 289 | Pixmap screenshotPixmap = getScreenshot(0, 0, 290 | Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true); 291 | /* 开始报错deviceCameraControl.getPictureData一直未null */ 292 | Pixmap cameraPixmap = new Pixmap( 293 | deviceCameraControl.getPictureData(), 0, 294 | deviceCameraControl.getPictureData().length); 295 | merge2Pixmaps(cameraPixmap, screenshotPixmap); 296 | // we could call PixmapIO.writePNG(pngfile, cameraPixmap); 297 | /* 仅保存screenshot,对同一时间的图片进行保存然后进行比较 */ 298 | Pixmap screenshotPixmap_test = getScreenshot(0, 0, 299 | Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true); 300 | FileHandle jpgfile_screenshot = Gdx.files 301 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date 302 | + "_screenshot.jpg"); 303 | deviceCameraControl.saveAsJpeg(jpgfile_screenshot, 304 | screenshotPixmap_test); 305 | /* 仅保存cameraPixma,对同一时间的图片进行保存然后进行比较 */ 306 | Pixmap cameraPixmap_test = new Pixmap( 307 | deviceCameraControl.getPictureData(), 0, 308 | deviceCameraControl.getPictureData().length); 309 | 310 | FileHandle jpgfile_cameraPixmap = Gdx.files 311 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date 312 | + "_camera.jpg"); 313 | deviceCameraControl.saveAsJpeg(jpgfile_cameraPixmap, 314 | cameraPixmap_test); 315 | 316 | /* 保存混合之后的相片 */ 317 | FileHandle jpgfile = Gdx.files 318 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date 319 | + ".jpg"); 320 | Gdx.app.log("FileHandle", date); 321 | time_1 = System.currentTimeMillis(); 322 | deviceCameraControl.saveAsJpeg(jpgfile, cameraPixmap); 323 | time_2 = System.currentTimeMillis(); 324 | /* 可以得到35830ms=35s,所以非常忙,导致Mode非常缓慢的回到Mode.normal */ 325 | Gdx.app.log("cost", String.valueOf(time_2 - time_1)); 326 | deviceCameraControl.stopPreviewAsync(); 327 | /* 保存文件后,mode回到normal继续render循环,所以中间停顿的其实是卡住了?! */ 328 | mode = Mode.normal; 329 | 330 | } 331 | } 332 | /* 这个log将会一直出现,所以render其实是一直在执行 */ 333 | // Gdx.app.log("mode", String.valueOf(mode)); 334 | // Gdx.app.log("mode", String.valueOf(i_render++)); 335 | } 336 | 337 | /* 随手加一个log是很重要的 */ 338 | public void takePicture4render() { 339 | /* 340 | * 进入app后,手按住屏幕不放,才能进入预览模式,放开就直接拍照了 341 | * input.isTouched(1)可能与button点击存在冲突,所以必须屏蔽 342 | */ 343 | // if (Gdx.input.isTouched(1)) { 344 | // 345 | // mode = Mode.normal; 346 | // Gdx.app.log("doube", String.valueOf(mode)); 347 | // } 348 | // 349 | // 350 | // if (Gdx.input.isTouched()) { 351 | // if (mode == Mode.normal) { 352 | // mode = Mode.prepare; 353 | // if (deviceCameraControl != null) { 354 | // deviceCameraControl.prepareCameraAsync(); 355 | // } 356 | // } 357 | // } else { 358 | // // touch removed 359 | // if (mode == Mode.preview) { 360 | // mode = Mode.takePicture; 361 | // } 362 | // } 363 | 364 | /* 我想让摄像头一直处于预览状态 */ 365 | // if (deviceCameraControl != null) { 366 | // deviceCameraControl.prepareCameraAsync(); 367 | // } 368 | 369 | /* 仅跟进入预览后直接进入拍照模式 */ 370 | if (mode == Mode.preview) { 371 | mode = Mode.takePicture; 372 | } 373 | 374 | // Gdx.gl20.glHint(GL20.GL_PERSPECTIVE_CORRECTION_HINT, 375 | // GL20.GL_NICEST);//old 54wall 376 | Gdx.gl20.glHint(GL20.GL_GENERATE_MIPMAP_HINT, GL20.GL_NICEST); 377 | if (mode == Mode.takePicture) { 378 | /* 没有清屏,摄像头的预览功能就没有 */ 379 | Gdx.gl20.glClearColor(0f, 0.0f, 0.0f, 0.0f); 380 | batch.begin(); 381 | stage.act(); // 更新舞台逻辑 382 | button.draw(batch, 1.0F);// 仅绘制actor 383 | stage.draw();// 绘制舞台 384 | batch.draw(texture, 0, 0, 960, 540); 385 | batch.end(); 386 | 387 | if (deviceCameraControl != null) { 388 | deviceCameraControl.takePicture(); 389 | 390 | } 391 | mode = Mode.waitForPictureReady; 392 | } else if (mode == Mode.waitForPictureReady) { 393 | Gdx.gl20.glClearColor(0.0f, 0f, 0.0f, 0.0f); 394 | batch.begin(); 395 | stage.act(); // 更新舞台逻辑 396 | button.draw(batch, 1.0F);// 仅绘制actor 397 | stage.draw();// 绘制舞台 398 | batch.draw(texture, 0, 0, 960, 540); 399 | batch.end(); 400 | 401 | } else if (mode == Mode.prepare) { 402 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0f, 0.0f); 403 | batch.begin(); 404 | stage.act(); // 更新舞台逻辑 405 | button.draw(batch, 1.0F);// 仅绘制actor 406 | stage.draw();// 绘制舞台 407 | batch.draw(texture, 0, 0, 960, 540); 408 | batch.end(); 409 | if (deviceCameraControl != null) { 410 | if (deviceCameraControl.isReady()) { 411 | deviceCameraControl.startPreviewAsync(); 412 | mode = Mode.preview; 413 | } 414 | } 415 | } else if (mode == Mode.preview) { 416 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0.0f, 0f); 417 | batch.begin(); 418 | stage.act(); // 更新舞台逻辑 419 | button.draw(batch, 1.0F);// 仅绘制actor 420 | stage.draw();// 绘制舞台 421 | batch.draw(texture, 0, 0, 960, 540); 422 | batch.end(); 423 | } else { 424 | /* mode = normal */ 425 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 426 | batch.begin(); 427 | stage.act(); // 更新舞台逻辑 428 | button.draw(batch, 1.0F);// 仅绘制actor 429 | stage.draw();// 绘制舞台 430 | batch.draw(texture, 0, 0, 960, 540); 431 | batch.end(); 432 | } 433 | Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT); 434 | 435 | batch.begin(); 436 | stage.act(); // 更新舞台逻辑 437 | button.draw(batch, 1.0F);// 仅绘制actor 438 | stage.draw();// 绘制舞台 439 | batch.draw(texture, 0, 0, 960, 540); 440 | batch.end(); 441 | 442 | Gdx.gl20.glEnable(GL20.GL_DEPTH_TEST); 443 | Gdx.gl20.glEnable(GL20.GL_TEXTURE); 444 | Gdx.gl20.glEnable(GL20.GL_TEXTURE_2D); 445 | // Gdx.gl20.glEnable(GL20.GL_LINE_SMOOTH);//54wall old 446 | Gdx.gl20.glEnable(GL20.GL_LINE_LOOP);// new 447 | Gdx.gl20.glDepthFunc(GL20.GL_LEQUAL); 448 | Gdx.gl20.glClearDepthf(1.0F); 449 | camera.update(true); 450 | // camera.apply(Gdx.gl20);//54wall old 451 | texture.bind(); 452 | for (int i = 0; i < 6; i++) { 453 | /* 454 | * 可以尝试直接使用上述代码,对一张渲染的图片进行剪切,或者使用三角形代替这里这么多的网格,然后看效果 455 | * http://blog.sina.com.cn/s/blog_940dd50a0101fl4s.html 456 | */ 457 | // mesh[i].render( GL20.GL_TRIANGLE_FAN, 0 ,4);//54wall old 458 | // ShaderProgram shader = new ShaderProgram(1 1);//原来的数目一样,不知道会不会影响 459 | // ShaderProgram shader = new ShaderProgram(String.valueOf(i), 460 | // String.valueOf(i+1));//54new 461 | // mesh[i].render(shader, GL20.GL_TRIANGLE_FAN, 0, 4);//54new 462 | } 463 | if (mode == Mode.waitForPictureReady) { 464 | /* 465 | * 注意deviceCameraControl.getPictureData()得到的是byte[],可见整体思路就是, 466 | * 将Android摄像头得到byte[],然后 467 | * 将byte[]转换为Pixmap,最后将pixmap存为jpg,这样不适用Android端图片保存模式, 468 | * byte[]----Pixmap----jpg 469 | */ 470 | if (deviceCameraControl.getPictureData() != null) { 471 | // camera picture was actually takentake Gdx Screenshot 472 | Pixmap screenshotPixmap = getScreenshot(0, 0, 473 | Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true); 474 | 475 | Pixmap cameraPixmap = new Pixmap( 476 | deviceCameraControl.getPictureData(), 0, 477 | deviceCameraControl.getPictureData().length); 478 | 479 | merge2Pixmaps(cameraPixmap, screenshotPixmap); 480 | // we could call PixmapIO.writePNG(pngfile, cameraPixmap); 481 | /* 现在有一个问题就是每次都是拍照两次,才有一张图片 */ 482 | FileHandle jpgfile = Gdx.files 483 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date 484 | + ".jpg"); 485 | Gdx.app.log("FileHandle", date); 486 | time_1 = System.currentTimeMillis(); 487 | deviceCameraControl.saveAsJpeg(jpgfile, cameraPixmap); 488 | 489 | time_2 = System.currentTimeMillis(); 490 | /* 可以得到35830ms=35s,所以非常忙,导致Mode非常缓慢的回到Mode.normal */ 491 | Gdx.app.log("cost", String.valueOf(time_2 - time_1)); 492 | deviceCameraControl.stopPreviewAsync(); 493 | /* 保存文件后,mode回到normal继续render循环,所以中间停顿的其实是卡住了?! */ 494 | mode = Mode.normal; 495 | 496 | } 497 | } 498 | /* 这个log将会一直出现 */ 499 | Gdx.app.log("mode", String.valueOf(mode)); 500 | } 501 | 502 | /* 注意截图与Android设备摄像传回的图像整合时并非按我所看的视角进行 */ 503 | private Pixmap merge2Pixmaps(Pixmap mainPixmap, Pixmap overlayedPixmap) { 504 | // merge to data and Gdx screen shot - but fix Aspect Ratio issues 505 | // between the screen and the camera 506 | Pixmap.setFilter(Filter.BiLinear); 507 | float mainPixmapAR = (float) mainPixmap.getWidth() 508 | / mainPixmap.getHeight(); 509 | float overlayedPixmapAR = (float) overlayedPixmap.getWidth() 510 | / overlayedPixmap.getHeight(); 511 | if (overlayedPixmapAR < mainPixmapAR) { 512 | int overlayNewWidth = (int) (((float) mainPixmap.getHeight() / overlayedPixmap 513 | .getHeight()) * overlayedPixmap.getWidth()); 514 | int overlayStartX = (mainPixmap.getWidth() - overlayNewWidth) / 2; 515 | // Overlaying pixmaps 516 | mainPixmap.drawPixmap(overlayedPixmap, 0, 0, 517 | overlayedPixmap.getWidth(), overlayedPixmap.getHeight(), 518 | overlayStartX, 0, overlayNewWidth, mainPixmap.getHeight()); 519 | } else { 520 | int overlayNewHeight = (int) (((float) mainPixmap.getWidth() / overlayedPixmap 521 | .getWidth()) * overlayedPixmap.getHeight()); 522 | int overlayStartY = (mainPixmap.getHeight() - overlayNewHeight) / 2; 523 | // Overlaying pixmaps 524 | mainPixmap.drawPixmap(overlayedPixmap, 0, 0, 525 | overlayedPixmap.getWidth(), overlayedPixmap.getHeight(), 0, 526 | overlayStartY, mainPixmap.getWidth(), overlayNewHeight); 527 | } 528 | return mainPixmap; 529 | } 530 | 531 | public Pixmap getScreenshot(int x, int y, int w, int h, boolean flipY) { 532 | 533 | Gdx.gl.glPixelStorei(GL20.GL_PACK_ALIGNMENT, 1); 534 | final Pixmap pixmap = new Pixmap(w, h, Format.RGBA8888); 535 | ByteBuffer pixels = pixmap.getPixels(); 536 | Gdx.gl.glReadPixels(x, y, w, h, GL20.GL_RGBA, GL20.GL_UNSIGNED_BYTE, 537 | pixels); 538 | 539 | final int numBytes = w * h * 4; 540 | byte[] lines = new byte[numBytes]; 541 | if (flipY) { 542 | final int numBytesPerLine = w * 4; 543 | for (int i = 0; i < h; i++) { 544 | pixels.position((h - i - 1) * numBytesPerLine); 545 | pixels.get(lines, i * numBytesPerLine, numBytesPerLine); 546 | } 547 | pixels.clear(); 548 | pixels.put(lines); 549 | } else { 550 | pixels.clear(); 551 | pixels.get(lines); 552 | } 553 | 554 | return pixmap; 555 | } 556 | 557 | @Override 558 | public void resize(int width, int height) { 559 | camera = new PerspectiveCamera(67.0f, 2.0f * width / height, 2.0f); 560 | camera.far = 100.0f; 561 | camera.near = 0.1f; 562 | camera.position.set(2.0f, 2.0f, 2.0f); 563 | camera.lookAt(0.0f, 0.0f, 0.0f); 564 | 565 | } 566 | 567 | @Override 568 | public void pause() { 569 | } 570 | 571 | @Override 572 | public void resume() { 573 | } 574 | 575 | ClickListener preview_on = new ClickListener() { 576 | 577 | @Override 578 | public void clicked(InputEvent event, float x, float y) { 579 | Gdx.app.log("preview_on", "preview_on按钮被点击了"); 580 | if (mode == Mode.waitForPictureReady) { 581 | mode = Mode.normal; 582 | } 583 | 584 | if (mode == Mode.normal) { 585 | mode = Mode.prepare; 586 | if (deviceCameraControl != null) { 587 | deviceCameraControl.prepareCameraAsync(); 588 | } 589 | } 590 | } 591 | 592 | }; 593 | 594 | 595 | ClickListener actor_move = new ClickListener() { 596 | 597 | @Override 598 | public void clicked(InputEvent event, float x, float y) { 599 | 600 | firstActor.setX(firstActor.getX() + 55); 601 | 602 | Gdx.app.log("actor_move", "actor_move按钮被点击了"); 603 | } 604 | 605 | }; 606 | 607 | ClickListener preview_on_1 = new ClickListener() { 608 | 609 | @Override 610 | public void clicked(InputEvent event, float x, float y) { 611 | Gdx.app.log("preview_on_1", "preview_on_1按钮被点击了"); 612 | if (mode == Mode.preview) { 613 | mode = Mode.takePicture; 614 | } 615 | 616 | } 617 | 618 | }; 619 | 620 | ClickListener preview_off = new ClickListener() { 621 | @Override 622 | public void clicked(InputEvent event, float x, float y) { 623 | Gdx.app.log("preview_on", "1按钮被点击了"); 624 | /* 625 | * 不等输入,直接写mode = 626 | * Mode.takePicture;相当于deviceCameraControl.prepareCameraAsync 627 | * ();没有写,会报空指针 java.lang.NullPointerException at 628 | * com.mygdx.game0606.android.AndroidDeviceCameraController 629 | * .takePicture(AndroidDeviceCameraController.java:122) 630 | */ 631 | 632 | /* 633 | * takePicture4render不能写在这里,因为batch.draw(texture, 0, 0, 960, 634 | * 540);应该在render中完成 635 | */ 636 | // takePicture4render(); 637 | /* 638 | * 增加下面语句后可以完成点击按钮进行拍照,关键就是让Mode进行一个完整的循环 639 | * 程序循环成Mode.normal时,屏幕再次回到黑色,才表示循环完成一次 640 | */ 641 | if (mode == Mode.waitForPictureReady) { 642 | mode = Mode.normal; 643 | } 644 | 645 | if (mode == Mode.normal) { 646 | mode = Mode.prepare; 647 | if (deviceCameraControl != null) { 648 | /* 649 | * 首先button的点击可能与Gdx.input.isTouched()输入检测有冲突,然后, 650 | * 通过仅屏蔽deviceCameraControl.prepareCameraAsync(); 651 | * 发现代码在render后 652 | * ,button依然有效,但是prepareCameraAsync后button失效,确认代码范围 653 | */ 654 | deviceCameraControl.prepareCameraAsync(); 655 | } 656 | } 657 | /* Mode.prepare之后不是Mode.preview,所以不能直接接入下边 */ 658 | // if (mode == Mode.preview) { 659 | // mode = Mode.takePicture; 660 | // } 661 | 662 | } 663 | }; 664 | 665 | } 666 | -------------------------------------------------------------------------------- /old_version/ver_2016.7.21.11.18/core/src/com/mygdx/game0606/actor/FirstActor.java: -------------------------------------------------------------------------------- 1 | package com.mygdx.game0606.actor; 2 | 3 | /** 4 | * @author 54wall 5 | * @date 创建时间:2016-7-21 下午1:16:58 6 | * @version 1.0 7 | */ 8 | import com.badlogic.gdx.Gdx; 9 | import com.badlogic.gdx.graphics.Texture; 10 | import com.badlogic.gdx.graphics.g2d.SpriteBatch; 11 | import com.badlogic.gdx.scenes.scene2d.Actor; 12 | 13 | public class FirstActor extends Actor { 14 | Texture texture; 15 | 16 | public void draw(SpriteBatch batch, float parentAlpha) { 17 | batch.draw(texture, this.getX(), this.getY()); 18 | } 19 | 20 | public Actor hit(float x, float y) { 21 | if (x > 0 && y > 0 && this.getHeight() > y && this.getWidth() > x) { 22 | return this; 23 | } else { 24 | return null; 25 | } 26 | } 27 | 28 | public boolean touchDown(float x, float y, int pointer) { 29 | // TODO Auto-generated method stub 30 | return false; 31 | } 32 | 33 | public void touchDragged(float x, float y, int pointer) { 34 | // TODO Auto-generated method stub 35 | } 36 | 37 | public void touchUp(float x, float y, int pointer) { 38 | // TODO Auto-generated method stub 39 | } 40 | 41 | public FirstActor(String name) { 42 | super(); 43 | texture = new Texture(Gdx.files.internal("data/james.png")); 44 | // this.height = texture.getHeight(); 45 | // this.width = texture.getWidth(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /old_version/ver_2016.7.21.11.18/core/src/com/mygdx/game0606/util/GetUrlImg.java: -------------------------------------------------------------------------------- 1 | package com.mygdx.game0606.util; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.net.MalformedURLException; 7 | import java.net.URL; 8 | 9 | import com.badlogic.gdx.Gdx; 10 | import com.badlogic.gdx.graphics.Pixmap; 11 | import com.badlogic.gdx.graphics.Pixmap.Format; 12 | import com.badlogic.gdx.graphics.Texture; 13 | import com.badlogic.gdx.graphics.g2d.TextureRegion; 14 | import com.badlogic.gdx.math.MathUtils; 15 | 16 | /** 17 | * @author 54wall 18 | * @date 创建时间:2016-7-21 下午3:51:09 19 | * @version 1.0 20 | * http://veikr.com/201203/libgdx_load_texture_network_async.html 21 | * libgdx中异步从网络加载图片 22 | */ 23 | public class GetUrlImg { 24 | 25 | public void getImg() throws MalformedURLException, IOException { 26 | /* 从url读取byte[] */ 27 | InputStream is = new URL("").openStream(); 28 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 29 | int length = 0; 30 | byte[] bytes = new byte[1024]; 31 | while ((length = is.read(bytes)) != -1) { 32 | out.write(bytes, 0, length); 33 | } 34 | is.close(); 35 | out.flush(); 36 | byte[] rtn = out.toByteArray(); 37 | 38 | /* 使用byte[]生成一个pixmap */ 39 | Pixmap pixmap = new Pixmap(bytes, 0, bytes.length); 40 | 41 | /* 将pixmap画到texture上 */ 42 | int width = pixmap.getWidth(); 43 | int height = pixmap.getHeight(); 44 | int preferWidth = MathUtils.nextPowerOfTwo(width); 45 | int preferHeight = MathUtils.nextPowerOfTwo(height); 46 | Texture texture = new Texture(preferWidth, preferHeight, 47 | pixmap.getFormat()); 48 | texture.draw(pixmap, 0, 0); 49 | pixmap.dispose(); 50 | /* 构造textureRegion */ 51 | TextureRegion region = new TextureRegion(texture, 0, 0, width, height); 52 | } 53 | 54 | public void name() { 55 | TextureRegion region = new TextureRegion(new Texture(1, 1, 56 | Format.RGBA8888)); 57 | loadTextureRegionFromUrl(region, "http://sss.com/asdf.png"); 58 | } 59 | 60 | public static void loadTextureRegionFromUrl(final TextureRegion region, 61 | final String url) { 62 | if (region == null) { 63 | throw new NullPointerException("region不能为空"); 64 | } 65 | new Thread() { 66 | @Override 67 | public void run() { 68 | /* 还没有新建ReaderHelper */ 69 | // final byte[] bytes = ReaderHelper.getBytesFromUrl(url); 70 | final byte[] bytes = null; 71 | System.out.println(url + " 图片获取成功:" + bytes.length); 72 | Gdx.app.postRunnable(new Runnable() { 73 | @Override 74 | public void run() { 75 | Pixmap pixmap = new Pixmap(bytes, 0, bytes.length); 76 | int width = pixmap.getWidth(); 77 | int height = pixmap.getHeight(); 78 | int preferWidth = MathUtils.nextPowerOfTwo(width); 79 | int preferHeight = MathUtils.nextPowerOfTwo(height); 80 | Texture texture = new Texture(preferWidth, 81 | preferHeight, pixmap.getFormat()); 82 | texture.draw(pixmap, 0, 0); 83 | pixmap.dispose(); 84 | region.setTexture(texture); 85 | region.setRegion(0, 0, width, height); 86 | System.out.println(region.getRegionWidth()); 87 | System.out.println(region.getRegionHeight()); 88 | System.out.println(region.getTexture().getHeight()); 89 | } 90 | }); 91 | }; 92 | }.start(); 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /readme_img/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/013d407bf363305f0fda6cbb4877f48527657439/readme_img/1.jpg -------------------------------------------------------------------------------- /readme_img/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/013d407bf363305f0fda6cbb4877f48527657439/readme_img/2.jpg -------------------------------------------------------------------------------- /readme_img/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/013d407bf363305f0fda6cbb4877f48527657439/readme_img/3.png -------------------------------------------------------------------------------- /readme_img/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/013d407bf363305f0fda6cbb4877f48527657439/readme_img/4.jpg -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include 'android', 'core' --------------------------------------------------------------------------------