OpenGL 2D游戏问题
我想使用 OpenGL 制作一款具有类似蠕虫的可破坏地形的 2D 游戏。
- 对此最好的方法是什么?
- 逐像素绘制像素? (呃,不好?)
- 将世界作为纹理并操纵它(这可能吗?)
提前致谢
I want to make a game with Worms-like destructible terrain in 2D, using OpenGL.
- What is the best approach for this?
- Draw pixel per pixel? (Uh, not good?)
- Have the world as a texture and manipulate it (is that possible?)
Thanks in advance
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
通常,我看到的做法是让每个实体都是一个带纹理的四边形,然后更新动画的纹理。对于可破坏的地形,最好将火车分成块,然后您只需更新已更改的块。不要使用 GLdrawpixels,它可能是最慢的方法(除了每帧从磁盘重新加载纹理之外,尽管它会很接近。)
Typically the way I have seen it done is to have each entity be a textured quad, then update the texture for animation. For a destructible terrain it might be best to break the train into tiles then you only have to update the ones that have changed. Don't use GLdrawpixels it is probably the slowest approach possible (outside of reloading textures from disk every frame though it would be close.)
我认为,但这只是一个简单的想法,一个好的方法可能是绘制大量的线条。
我认为您将景观表示为一堆线段,对于屏幕的每一列,您都有 0..n 条垂直线,它们构成了地面:
在上面的精彩内容中, “0”列:s 组成一行,依此类推。我没有尝试说明单个像素列有多于一行的情况,因为这种粗略格式有点困难。
我不确定这是否有效,但它至少有一定的意义,因为线条是 OpenGL 基元。
您可以通过启用纹理映射并为每个线段指定所需的纹理坐标来对线条进行着色和纹理化。
I think, but this is just a quick idea, that a good way might be to draw a Very Large Number of Lines.
I'm thinking that you represent the landscape as a bunch of line segments, for each column of the screen you have 0..n vertical lines, that make up the ground:
In the above awesomeness, the column of "0":s makes up a single line, and so on. I didn't try to illustrate the case where a single pixel column has more than one line, since it's a bit hard in this coarse format.
I'm not sure this will be efficient, but it at least makes some sense since lines are an OpenGL primitive.
You can color and texture the lines by enabling texture-mapping and specifying the desired texture coordinates for each line segment.
我想我首先将前景绘制到模板缓冲区中,以便模板缓冲区在有前景的任何地方设置为 1 位,在其他地方(您希望显示天空的位置)设置为 0。
然后,要绘制框架,请绘制天空、启用模板缓冲区并绘制前景。对于初始帧(在任何爆炸破坏部分前景之前),模板缓冲区不会真正执行任何操作。
然而,当确实发生爆炸时,您将其绘制到模板缓冲区(清除该圆圈的模板缓冲区)。然后像以前一样重新绘制数据:绘制天空,启用模板缓冲区,然后绘制前景。
这可以让您获得所需的效果(前景在需要的地方消失),而无需修改前景纹理。如果您不想使用模板缓冲区,对我来说显而易见的替代方案是启用混合,并仅操纵前景纹理的 Alpha 通道 - 将受爆炸影响的 Alpha 设置为 0(透明) 。 IMO,模板缓冲区是一种更干净的方法,但操作 Alpha 通道也非常简单。
I think I would start by drawing the foreground into the stencil buffer so the stencil buffer is set to 1 bits anywhere there's foreground, and 0 elsewhere (where you want your sky to show).
Then to draw a frame, you draw your sky, enable the stencil buffer, and draw the foreground. For the initial frame (before any explosion has destroyed part of the foreground) the stencil buffer won't really be doing anything.
When you do have an explosion, however, you draw it to the stencil buffer (clearing the stencil buffer for that circle). Then you re-draw your data as before: draw the sky, enable the stencil buffer, and draw the foreground.
This lets you get the effect you want (the foreground disappears where desired) without having to modify the foreground texture at all. If you prefer not to use the stencil buffer, the alternative that seems obvious to me would be to enable blending, and just manipulate the alpha channel of your foreground texture -- set the alpha to 0 (transparent) where it's been affected by an explosion. IMO, the stencil buffer is a bit cleaner approach, but manipulating the alpha channel is pretty simple as well.
我想象的方式是这样的:
当某物爆炸时,您可以对纹理(显示背景)和“可步行”路径进行布尔运算(矩形-圆形)。
我想说的是,你进行几何布尔运算,然后使用结果来更新纹理(使用 alpha 掩码或其他东西)并更新用于跟踪可步行区域的数据结构(无论哪种可能)是)。
将事物分开,而不是仅仅依赖于 gl draw 方法
The way I imagine it is this:
When something explodes, you do a boolean operation (rectangle-circle) for the texture(revealing the background) and for the 'walkable' path.
What I'm trying to say is you do a geometric boolean operation and you use the result to update the texture(with an alpha mask or something) and update the data structure you use to keep track of the walkable area(which ever that might be).
Split things up, instead of relying only on gl draw methods
我假设你的问题是实现角色/武器/地形之间的碰撞。
只要您不在 opengl es 上执行此操作,您就可以摆脱使用模板缓冲区进行每像素碰撞检测并使地形成为单个可修改纹理的情况。
此页面将给出一个想法:
http://kometbomb.net/2007 /07/11/硬件加速2d-碰撞检测-in-opengl/
I'm assuming your problem will be to implement the collision between characters/weapons/terrain.
As long as you aren't doing this on opengl es, you might be able to get away with using the stencil buffer to do per-pixel collision detection and have your terrain be a single modifyable texture.
This page will give an idea:
http://kometbomb.net/2007/07/11/hardware-accelerated-2d-collision-detection-in-opengl/
我想你最好使用具有正确映射的纹理填充多边形(一种线性多边形,不会拉伸纹理以使用所有纹理像素,但会保留裁剪区域),然后在它们被破坏时重新塑造它们。
I guess you'd better use texture-filled polygons with the correct mapping (a linear one that doesn't stretch the texture to use all the texels, but leaves the cropped areas out), and then reshape them as they get destroyed.
考虑到《百战天虫》地形的样子,我想到了这个想法。但我不确定你如何在 OpenGL 中实现它。它更像是一种分层的 2D 绘图方法。无论如何我都会发布这个想法。我已经使用 Paint.NET 模拟了该方法。
首先,你有一个背景天空层。
你有一个地形层。
地形图层被遮罩,因此顶部部分不会被绘制。在天空层之上绘制地形层以形成场景。
现在是主要思想。每当发生爆炸或其他地形变形事件时,您都可以在地形图层上绘制圆形或其他形状,使用地形图层本身作为绘图遮罩(因此仅绘制与现有地形重叠的圆形部分),消灭部分地形。使用透明/蒙版颜色画笔进行填充,并使用与地形相似的颜色作为粗笔。
您可以重复此过程以添加更多变形。您可以将此图层保留在内存中并在发生变形时添加变形,或者如果没有太多变形需要渲染,您甚至可以在每一帧中将它们渲染在内存中。
Thinking about the way Worms terrain looked, I came up with this idea. But I'm not sure how you would implement it in OpenGL. It's more of a layered 2D drawing approach. I'm posting the idea anyway. I've emulated the approach using Paint.NET.
First, you have a background sky layer.
And you have a terrain layer.
The terrain layer is masked so the top portion isn't drawn. Draw the terrain layer on top of the sky layer to form the scene.
Now for the main idea. Any time there is an explosion or other terrain-deforming event, you draw a circle or other shape on the terrain layer, using the terrain layer itself as a drawing mask (so only the part of the circle that overlaps existing terrain is drawn), to wipe out part of the terrain. Use a transparent/mask-color brush for the fill and some color similar to the terrain for the thick pen.
You can repeat this process to add more deformations. You could keep this layer in memory and add deformations as they occur or you could even render them in memory each frame if there aren't too many deformations to render.