博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
看博客学学Android(十八)
阅读量:7180 次
发布时间:2019-06-29

本文共 5214 字,大约阅读时间需要 17 分钟。

原文地址:

 

I thought about posting a YouTube video of the gameplay. I used recordmydesktop program to record videos in the past, but the problem is that libGDX and rmd do not sync so I get a lot of artifacts on the screen, sprites are cut in half, etc. I searched and found some useful articles about it. Basically, one would record each frame to a PNG file and then create a video out of it. Of course, this requires a lot of disk space, but that's not an issue. I found this page really helpful:

However, their code has some weak points. For some reason, when I overlay background with sprites with semi-transparent pixels, the resulting PNG file has semi-transparent pixels in that area. Producing a video from it yields some really ugly artifacts. I tried different settings, even changed my render code, but the problem remained. Now, a simple post-processing step using ImageMagick (adding black background) fixes the problem, so I figured if I'm going to post-process it anyway, I might do the vertical flip in ImageMagick as well. So I turned off the y-flip in the code. This makes it more efficient: there is no need to allocate w*h*4 bytes of memory on each frame. On 800x480 screen, that's about 1.5MB allocate on each frame!

Also, the code that deals with framerate (skipping frames) is really sub-optimal. It skips the file numbers, which is not a big deal, but it also creates a new ScreenShot object each frame, which is completely not needed. For example, if you are recording at 30fps and game runs at 60fps, you're creating new object 50% of the time.

Finally, the code seems to forget to dispose of pixmap, so if you run it for a really long time, if would eat all your RAM.

So, I yanked out the whole FPS code out of ScreenShot class, and leave that to the class that sets up countinous screenshots instead. I also noted that some of the variables are initialized but never used. My ScreenShot class is much simpler and straightforward:

public class ScreenShot implements Runnable{    private static int fileCounter = 0;    private Pixmap pixmap;    @Override    public void run()    {        saveScreenshot();    }    public void prepare()    {        getScreenshot(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false);    }    public void saveScreenshot()    {        FileHandle file = new FileHandle("/tmp/shot_"+ String.format("%06d",  fileCounter++) + ".png");        PixmapIO.writePNG(file, pixmap);        pixmap.dispose();    }    public void getScreenshot(int x, int y, int w, int h, boolean flipY)    {        Gdx.gl.glPixelStorei(GL10.GL_PACK_ALIGNMENT, 1);        pixmap = new Pixmap(w, h, Pixmap.Format.RGBA8888);        Gdx.gl.glReadPixels(x, y, w, h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, pixmap.getPixels());    }}

Yep, that's all. In render loop I use this at and of each render:

ScreenShot worker = new ScreenShot();worker.prepare();			// grab screenshotexecutor.execute(worker);	// delayed save in other thread

For completeness, executor added to my Screen subclass:

private ExecutorService executor;...executor = Executors.newFixedThreadPool(25);

Now, on my Core2Duo it has a hard time keeping up frame rate. On one hand, it's good, because gameplay slows down and I'm able to play a nice, partly scripted video. On the other hand, it would be nicer to just record and later cut out what you need. So I added a hotkey for screenshots. It only records shots while S is pressed on the keyboard. When you record a few interesting seconds, just release S and let the PNG writer catch up. When it does, and CPU load goes back to normal, you can record again.

Videos created like this are super easy to edit. Just remove the unneeded PNG files and compress video without them. It's also easy to sync with music, because you can add/remove frames at will.

Turning screenshots into YouTube video

Since Android screen I'm using by default is 480x800 pixels, the closest fit is YouTube's 1280x720 format. We need to scale the image to 432x720 to maintain aspect ratio. This leaves us with a lot of unused area. You can put your logo there, or even show 2 videos running side-by-side ;) I decided to put the video inside another rectangle, that resembles a handheld device, so it's even smaller, it's 372x620.

Anyway, I created a 1280x720 static image with my logo and now I'm blending the gameplay into it, and also flipping it vertically. On Linux, I'm using a command like this:

for i in shot*png; do echo $i; convert $i -flip -filter Lanczos -resize 372x620 temp1.png; composite temp1.png back.png -geometry +126+56 $i; done

Once all the images are ready, we can run mencoder to produce the video. YouTube recommends using H.264 format and bitrate up to 5000 for 720p videos. They also recommend two B-frames. Here's my command:

mencoder mf://shot*.png -mf w=1080:h=720:fps=25:type=png -ovc x264 -audiofile music.mp3 -oac copy -o movie.avi -x264encopts bitrate=5000:bframes=2:subq=6:frameref=3:pass=1:nr=2000

This yields a solid quality YT video of your gameplay. You can see the result at the start of this post. As for the audio, I just slapped over the game's soundtrack. I'm not capturing the audio of the actual game.

转载于:https://www.cnblogs.com/NorthDrift/p/3432389.html

你可能感兴趣的文章
细读 JavaScript 之静态作用域与动态作用域区别
查看>>
深入理解Java虚拟机第7章思维导图-虚拟机类加载机制
查看>>
【译】函数式的React
查看>>
Redis 和 Memcached 的区别大吗?只选一个做缓存我们该选哪个?
查看>>
跟父亲一样伟大的程序员,请一定要照顾好自己!
查看>>
java B2B2C Springboot电子商城系统-高可用的服务注册中心
查看>>
CSS技巧:Flex弹性布局大型攻略
查看>>
UVC摄像头-学习
查看>>
深入理解多线程(四)—— Moniter的实现原理
查看>>
前端面试中常考的源码实现
查看>>
vue基于viewer实现的图片查看器
查看>>
HTML、CSS、JavaScript
查看>>
Html5的新特性总结
查看>>
来一个阿里妈妈字体图标的简单说明书吧
查看>>
git 入门教程之撤销更改
查看>>
React在线编辑国际化文本
查看>>
了解多线程!
查看>>
Android Jetpack架构组件之 Paging(使用、源码篇)
查看>>
Day 4
查看>>
面向对象(理解对象)——JavaScript基础总结(一)
查看>>