如何在2D文字游戏上叠加图形效果(类似终端模拟器)?
我正在开发一个以故事为主的2D游戏,界面像一个终端模拟器,我想加入一些图形效果,比如老电视屏幕的扭曲效果。现在所有的组件都是用Python 3.4写的,游戏需要能够在不同平台上运行(我在Mac上工作)。性能不是特别关键。游戏的主要窗口包含:
- 终端界面(游戏在这里进行)
- 菜单覆盖层(处理加载/保存功能以及选项等)
- 图形覆盖层(在其他输出上渲染图形效果)。
到目前为止,我尝试了两种解决方案,一种是用Qt5
,另一种是用SDL2
,但我更想讨论Qt5
的做法。使用Qt5
,我已经成功实现了终端界面(QTextEdit
)和菜单覆盖层(QGraphicsView
),但我在整合图形效果覆盖层时遇到了问题。我考虑过使用OpenGL
着色器或QGraphicsEffect
,但后者在Mac OS X上无法使用。
我一直在使用vispy.gloo
来进行OpenGL
调用,而使用SDL2
的方法,我能够实现一个基于着色器的图形效果。
根据这个链接,我尝试将这些效果整合到QMainWindow
中,作为现有内容的覆盖层(下面的代码示例没有包含任何图形效果),但首先,这篇帖子并没有真正解决我的问题,其次,我遇到了Qt5
的一个已知bug(这个链接)。
我非常感谢任何关于图形效果可能的实现想法,也欢迎推荐新的框架。非常感谢!
Qt5实现的代码示例:
class MainWindow(QtWidgets.QMainWindow): # {{{1
"""Extension of the QMainWindow class."""
def __init__(self, central=None, overlay=None, parent=None):
"""Constructor."""
super(MainWindow, self).__init__(parent)
self.parent = parent
# For readability of the output, set a minimum size
self.setMinimumSize(680, 480)
# Create the central widget containing the terminal and focus
self.widget = central # Instance of QTextEdit
self.setCentralWidget(self.widget)
self.setFocusProxy(self.widget)
# Create the menu overlay
self.menu_overlay = overlay # Instance of QGraphicsView
self.menu_overlay.setParent(self)
# Here, I would like to add the graphics effect (old TV screen) overlaid
# on top of the central widget and the menu overlay. The g-e have to be
# transparent to keyboard and mouse events.
# Resize and show the main window.
self.resize(1024, 768)
self.show()
def resizeEvent(self, event):
"""Resizes all child widgets that are not automatically resized (e.g. overlays)."""
pass
1 个回答
1
我找到了解决我问题的方法。不过,不幸的是,我不得不从Python转向QML来实现这个图形效果。
根据Qt的QtQuick教程(http://qt-project.org/doc/qt-5/qtquick-shadereffects-example.html),下面这段代码可以创建一个OpenGL的着色器效果,它的输入来自另一个QML元素:
import QtQuick 2.2
import QtQuick.Window 2.1
Window {
id: win
visible: Window.AutomaticVisibility
width: 640
height: 480
Rectangle {
id: theItem
anchors.horizontalCenter: parent.horizontalCenter
// [...] your content here
}
ShaderEffectSource {
id: theSource
sourceItem: theItem
}
ShaderEffect {
id: shader
anchors.centerIn: theItem
width: theItem.width
height: theItem.height
property variant u_sampler: theSource
fragmentShader:
// [...] any shader program using the following parameters:
"uniform float qt_Opacity;" +
"uniform sampler2D u_sampler;" +
"varying vec2 qt_TexCoord0;" +
"void main(void) {" +
" vec4 color = texture2D(u_sampler, qt_TexCoord0);" +
" color.a = qt_Opacity;" +
" gl_FragColor = color;" +
"}"
}
}