概要
とあるゲームにてバトルが始まるときのフェードアウト表現(黒い線が画面を回りながら暗転する)をどう実装すればいいのか考えて簡易的に実装してみましたという記事です。
実装
ubuntu18.04環境で、python3, pyqt5を使用しました。
インストール
# pyqt5 install
pip3 install pyqt5
処理
以下の2stepです
- step1. コマンド実行時点のスクリーンショットを撮る
- step2. 黒色のブロックをpyqt5で順番に表示
step1. コマンド実行時点のスクリーンショットを撮る
# スクリーンショット
gnome-screenshot -f test.png
step2. 黒色のブロックをpyqt5で順番に表示
# -*- coding:utf-8 -*-
## qt5
from PyQt5.QtWidgets import *
from PyQt5 import QtCore, QtGui
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QSizePolicy
from PyQt5.QtGui import QImage, QPalette, QPixmap
# 追加したimport
from PyQt5.QtGui import QPainter, QFont, QColor, QPen
from PyQt5.QtCore import Qt
import sys
import time
from time import sleep
class Window(QMainWindow):
def __init__(self):
super(QMainWindow, self).__init__()
self.image = QImage("./test.png")
# 事前に任意のサイズにリサイズしておくと後処理が楽
# gnome-screenshot -f test.png などでキャプチャしておく
self.window = QWidget()
self.window.setWindowTitle('Image View')
self.window.setFixedSize(self.image.width(), self.image.height())
self.setFixedSize(self.image.width(), self.image.height())
self.painter = QPainter()
self.imageLabel = QLabel()
self.layout = QVBoxLayout()
# creating a timer object
self.TimerUpdate_mSec = 15
self.TimerUpdate_cnt = 0
self.TimerUpdate_cnt_step = 0
timer = QTimer(self)
timer.timeout.connect(self.callback_draw)
timer.start(self.TimerUpdate_mSec)
# timer callback function
def callback_draw(self):
# -----
# 加工したいイメージを渡して編集開始
self.painter.begin(self.image)
# 塗りつぶし範囲指定
img_width = self.image.width()
img_height = self.image.height()
block_ratio = 13 #10
x_size = img_width/block_ratio #100
y_size = img_height/block_ratio #100
## 0
current_position=int(self.TimerUpdate_cnt_step%4) #0,1,2,3
loop_cnt=int(self.TimerUpdate_cnt_step/4)
#print(str(current_position)+" "+str(loop_cnt))
if current_position == 0:
x_pos = int((self.TimerUpdate_cnt+loop_cnt) * x_size % img_width)
y_pos = int(loop_cnt * y_size % img_height)
#y_pos = int(self.TimerUpdate_cnt * x_size / img_width) * y_size
if self.TimerUpdate_cnt >= block_ratio-1-loop_cnt:
self.TimerUpdate_cnt = 0
self.TimerUpdate_cnt_step += 1
self.TimerUpdate_cnt += 1
## 1
elif current_position == 1:
x_pos = int((block_ratio-1-loop_cnt) * x_size % img_width)
y_pos = int((self.TimerUpdate_cnt+loop_cnt) * y_size % img_height)
if self.TimerUpdate_cnt >= block_ratio-1-loop_cnt+1:
self.TimerUpdate_cnt = 0
self.TimerUpdate_cnt_step += 1
self.TimerUpdate_cnt += 1
## 2
elif current_position == 2:
x_pos = int((block_ratio-1-self.TimerUpdate_cnt-loop_cnt) * x_size % img_width)
y_pos = int((block_ratio-1-loop_cnt) * y_size % img_height)
if (block_ratio-1-self.TimerUpdate_cnt <= loop_cnt):
self.TimerUpdate_cnt = 0
self.TimerUpdate_cnt_step += 1
self.TimerUpdate_cnt += 1
## 3
elif current_position == 3:
x_pos = int(loop_cnt * x_size % img_width)
y_pos = int((block_ratio-1-self.TimerUpdate_cnt-loop_cnt) * y_size % img_height)
if (block_ratio-1-self.TimerUpdate_cnt <= loop_cnt+1):
self.TimerUpdate_cnt = 0
self.TimerUpdate_cnt_step += 1
else:
self.TimerUpdate_cnt += 1
print(str(x_pos) + " " + str(y_pos))
self.painter.fillRect(x_pos, y_pos, x_size, y_size, Qt.black)
self.painter.end()
# -----
# ラベルに読み込んだ画像を反映
self.imageLabel.setPixmap(QPixmap.fromImage(self.image))
self.layout.addWidget(self.imageLabel)
self.window.setFixedSize(self.image.width(), self.image.height())
self.window.resize(self.image.width(), self.image.height())
self.window.setLayout(self.layout)
#self.window.show()
self.window.showFullScreen()
#self.TimerUpdate_cnt += 1
if self.TimerUpdate_cnt_step >= 25:
print("end")
time.sleep(self.TimerUpdate_mSec*0.001/4)
sys.exit(0)
if __name__ == '__main__':
# create pyqt5 app
app = QApplication(sys.argv)
# create the instance of our Window
window = Window()
# start the app
sys.exit(app.exec())
以下の通り実行するだけ
gnome-screenshot -f test.png
python3 test.py
bash test.sh
入力画像のサイズによっては黒いブロックがずれることがあるので、
入力画像に応じて、ブロックのサイズや、カウンターの最大値は適宜変更するとよい。
感想
簡易的に実装しただけでもっとpyqt5や、グラフィックライブラリを使えるようになりたい。
OpenGL、Qt transparent機能を利用するとより改善されるなど、ご意見があれば頂けると嬉しいです。
追記:
回転が逆回転のような気もしますが、気にしないで下さい。。
https://youtu.be/JlY3585-rKk?t=55
参考
https://doc.qt.io/qt-5/qwidget.html
QImage の読み書きあれこれ
Python + PyQt5 画像の上に文字や矩形を上書き(drawText, drawRect, fillRect)
【初心者向け】PythonとPyxelでゲームプログラミングを始める一番簡単な方法