游戏引擎理论与实现系列03-生成图像
来源:互联网 发布:eplan软件 64位 编辑:程序博客网 时间:2024/05/01 01:16
- Tick机制
- Bitmap位图
- RGB
- Alpha通道
- 色彩深度编辑
- Bitmap Class
- Screen
- Drawing a Bitmap
- Scanning a Bitmap
- Load Image
- 主程序
- 缓冲策略
- BufferImage and Raster DataBuffer
- DrawImage
- 参考资料
Tick机制
public class Ticker { public void tick() { }}
游戏服务器程序内部都会统一设计所谓的tick机制,这个机制一般来说有两个用途,一是许多业务模块都会有定时处理的需求,如:游戏中一天时间的轮转;二是游戏服务器内部会有一些日常主动驱动的事件,如:水,火山熔浆动画,这些都在tick中处理。关于tick机制的实现和其中一些问题, 我们将来会详细介绍和探讨,对于现在, 我们只需从整体结构上知道tick机制的存在和重要性。
Bitmap(位图)
又称栅格图(Raster graphics),是使用像素阵列(Pixel-array/Dot-matrix點陣)来表示的图像。
根据位深度,可将位图分为1、4、8、16、24及32位图像等。每个像素使用的信息位数越多,可用的颜色就越多,颜色表现就越逼真,相应的数据量越大。例如,位深度为 1 的像素位图只有两个可能的值(黑色和白色),所以又称为二值位图。位深度为 8 的图像有 28(即 256)个可能的值。位深度为 8 的灰度模式图像有 256 个可能的灰色值。
RGB图像由三个颜色通道组成。8 位/像素的 RGB 图像中的每个通道有 256 个可能的值,这意味着该图像有 1600 万个以上可能的颜色值。有时将带有 8 位/通道 (bpc) 的 RGB 图像称作 24 位图像(8 位 x 3 通道 = 24 位数据/像素)。通常使用24位RGB组合数据位表示的的位图称为真彩色位图。
RGB
位图颜色的一种编码方法,用红(Red)、绿(Green)、蓝(Blue)三原色的光学强度来表示一种颜色。这是最常见的位图编码方法,可以直接用于屏幕显示。
Alpha通道
在原有的图片编码方法基础上,增加像素的透明度信息。图形处理中,通常把RGB三种颜色信息称为红通道、绿通道和蓝通道,相应的把透明度称为Alpha通道。多数使用颜色表的位图格式都支持Alpha通道。
色彩深度[编辑]
色彩深度又叫色彩位数,即位图中要用多少个二进制位来表示每个点的颜色,是分辨率的一个重要指标。常用有1位(单色),2位(4色,CGA),4位(16色,VGA),8位(256色),16位(增强色),24位和32位(真彩色)等。色深16位以上的位图还可以根据其中分别表示RGB三原色或CMYK四原色(有的还包括Alpha通道)的位数进一步分类,如16位位图图片还可分为R5G6B5,R5G5B5X1(有1位不携带信息),R5G5B5A1,R4G4B4A4等等。
Bitmap Class
本引擎所有的图形操作都是通过Bitmap与Screen或图形缓存来完成。我们会发现, Bitmap其实是非常简单。我们从介绍Bitmap类的定义开始。每个像素Pixel为一个32bit 的整数, 因此可以支持24位RGB组合数据位和Alpha通道。 所有的Pixel保存在一个数组结构Pixels中。
public class Bitmap { protected int width; protected int height; protected int[] pixels; public Bitmap(int width, int height) { this.width = width; this.height = height; this.pixels = new int[width * height]; } public int getWidth() { return width; } public int getHeight() { return height; } public int[] getPixels() { return pixels; }}
Screen
屏幕实质上就是一大Bitmap.
public class Screen extends Bitmap { public Screen(int width, int height) { super(width, height); } public void render(Ticker ticker, Bitmap bitMap) { this.putBitmap(bitMap, 0, 0); }}
Drawing a Bitmap
以上介绍了Bitmap, 接下我们介绍如何将将一个Bitmap 画到另外一个Bitmap,最常见的,比如,将Bitmap画到屏幕上,对应左上角的位置为(offX, offY)
透明色
public void putBitmap(Bitmap bitmap, int offX, int offY) { int w = bitmap.getWidth(); int h = bitmap.getHeight(); int[] p = bitmap.getPixels(); int[] screenPixels = super.pixels; int posX = 0, posY = 0; for (int y = 0; y < h; y++) { posY = offY + y; if (posY < 0 || posY >= super.height) { continue; } int screenRowOffset = posY * width; int bitmapRowOffset = y * w; for (int x = 0; x < w; x++) { posX = offX + x; if (posX < 0 || posX >= super.width) { continue; } screenPixels[screenRowOffset + posX] = p[bitmapRowOffset + x]; } } }
Scanning a Bitmap
该函数是putBitmap函数的反向函数,用于获取对应bitmap覆盖的屏幕位置。 注意该返回对象时通过传参数实现的。
public void getBitMap(BitMap bitmap, int offX, int offY) { int w = bitmap.getWidth(); int h = bitmap.getHeight(); int[] bitMapPixels = bitmap.getPixels(); int[] screenPixels = super.pixels; int posX = 0, posY = 0; int pixel; for (int y = 0; y < h; y++) { posY = offY + y; if (posY < 0 || posY >= super.height) { continue; } int screenRowOffset = posY * width; int bitmapRowOffset = y * w; for (int x = 0; x < w; x++) { posX = offX + x; if (posX < 0 || posX >= super.width) { continue; } pixel = screenPixels[screenRowOffset + posX]; if(pixel!=0){ bitMapPixels[bitmapRowOffset + x] = pixel; } } } }
Load Image
读取图像文件并保存到Bitmap。
public class ImageLoader { public static BitMap floors = load("/tex/floors.png"); private static BitMap load(String filename) { try { URL url = ImageLoader.class.getResource(filename); BufferedImage img = ImageIO.read(url); int w = img.getWidth(); int h = img.getHeight(); BitMap result = new BitMap(w, h); int[] pixels = result.getPixels(); img.getRGB(0, 0, w, h, pixels, 0, w); return result; } catch (IOException e) { throw new RuntimeException(e); } }}
主程序
缓冲策略
public void createBufferStrategy(int numBuffers)
生成多缓冲(Multi-buffering)策略, 多缓冲(Multi-buffering)的方式可以显著地改善渲染性能。它将始终根据该缓冲区数参数来创建 bufferstrategy 。首先尝试翻页的缓冲区交换(page-flipping) 策略,然后使用加速缓冲区尝试blitting 策略,最后使用不加速的blitting 策略。
BufferStrategy bs = this.getBufferStrategy(); if (bs == null) { this.createBufferStrategy(3); return;// skip one render }
BufferImage and Raster DataBuffer
生成和屏幕一样尺寸的图像缓存BufferedImage。 并用screenPixels指向对应缓存数据的的数组, 以方便程序的操作。
private BufferedImage screenImage; private int[] screenPixels;
this.screenImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB); DataBufferInt buffer = (DataBufferInt) screenImage.getRaster().getDataBuffer(); this.screenPixels = buffer.getData();
DrawImage
Bitmap floors = ImageLoader.sprites; this.screen.render(ticker,floors); for (int i = 0; i < this.screen.getPixels().length; i++) { this.screenPixels[i] = this.screen.getPixels()[i]; } Graphics g = bs.getDrawGraphics(); g.drawImage(this.screenImage, 0, 0, WIDTH * SCALE, HEIGHT * SCALE, null); g.dispose(); bs.show();
- 获取Bitmap对象
- 将Bitmap对象画到对应的屏幕对象
- 通过循环,将Screen Bitmap 像素设置到 屏幕缓存像素数组
- 将屏幕缓存像素数组显示。
参考资料
维基百科-位图
- 游戏引擎理论与实现系列03-生成图像
- 游戏引擎理论与实现系列01-生成窗口
- 游戏引擎理论与实现系列04-画线和裁剪
- 游戏引擎理论与实现系列02-主控线程和循环
- Android/Ophone平台2D游戏引擎实现系列文章
- 【游戏理论】游戏与游戏开发
- 物理引擎与游戏引擎
- Unity3D 游戏引擎入门教程系列
- 游戏引擎与游戏引擎开发入门
- 游戏服务器引擎实现
- 游戏与引擎
- 游戏引擎与框架
- 游戏引擎与C++
- 3D游戏引擎设计与实现(1)
- 3D游戏引擎设计与实现(2)
- 3D游戏引擎设计与实现(3)
- 3D游戏引擎设计与实现(4)
- 3D游戏引擎设计与实现(5)
- setting Putty' color like an Ubuntu terminal (continuously updated)
- 【Leetcode】Permutations
- OpenGL--动作管理
- 游戏引擎理论与实现系列01-生成窗口
- mysqldump 备份
- 游戏引擎理论与实现系列03-生成图像
- ABAP 例程程序在SAP BW TRANFORMATION中的应用,去除非法字符
- [Leetcode] 126. Word Ladder II
- [Leetcode] 127. Word Ladder
- Blog hello world
- WPF Commend 命令
- 3月30日--4月8日(共20小时,剩3800小时)
- 查看路由信息的几种方法
- 【spring-mvc】SpringMVC中的转发与重定向