GTKを使って、アニメなどでよくあるオペレータやハッカーっぽい人がなんか外部から攻撃を受けているとき画面いっぱいに警告ウィンドウが出てくるアレをつくりました。
動作環境
- Ubuntu 14.04
- Ruby 2.2.0
- gtk2 3.0.7 (gem)
必要なもののインストール
$ gem install gtk2
ソースコード
使用した画像はソースコードと併せてここ(→ https://gist.github.com/seinosuke/9e615852063807427dab )においてあります。自分ではしょぼい画像しかつくれなかったので、もっとそれっぽい画像を用意すればそれっぽさが増すと思います。
ソースコードは以下の通りです。Rubyです。
main.rb
require 'gtk2'
include Math
WIDTH = 1280 # 画面の幅
HEIGHT = 800 # 画面の高さ
MAX = 30 # 表示するウィンドウの数
# 使用する色
COLOR_DICT = {
:yellow => Gdk::Color.new(65535, 65535, 0),
:black => Gdk::Color.new(0, 0, 0),
}
colormap = Gdk::Colormap.system
COLOR_DICT.each do |_, color|
colormap.alloc_color(color, false, true)
end
# 生成される警告ウィンドウ
class WarningWindow < Gtk::Window
def initialize
super(Gtk::Window::POPUP)
@width = 300 # ウィンドウの幅
@height = 150 # ウィンドウの高さ
m = [WIDTH/2 - @width/2, HEIGHT/2 - @height/2]
s = [WIDTH/8, HEIGHT/8]
@x, @y = box_muller(m, s)
@x_adder = [-2, -1, 1, 2].sample
@y_adder = [-2, -1, 1, 2].sample
self.move(@x, @y)
self.set_size_request(@width, @height)
self.set_app_paintable(true)
self.set_title("WARNING!!")
self.realize
@drawable = self.window
@gc = Gdk::GC.new(@drawable)
@gc.set_line_attributes(20, Gdk::GC::LINE_SOLID, Gdk::GC::CAP_ROUND, Gdk::GC::JOIN_BEVEL)
# 画像を表示
source = ["./msg_warning.png", "./msg_danger.png"].sample
@image = Gtk::Image.new(source)
self.add(@image)
# 縞模様用のカウンタ
@counters = (-1..5).map do |i|
->(init, max) do
n = init
-> { n == max - 1 ? n = -50 : n += 1 }
end[i*50, @width]
end
end
# 縞模様を流すアニメーション
def add_task
Gtk.timeout_add(20) do
@x += @x_adder
@y += @y_adder
@x_adder *= -1 if @x < 0 || @x > WIDTH - @width
@y_adder *= -1 if @y < 0 || @y > HEIGHT - @height
# self.move(@x, @y)
clear
draw
end
end
# 黒い斜め線を描画
def draw
@gc.set_foreground(COLOR_DICT[:black])
@counters.each do |counter|
from = [counter[], 0]
to = [from[0] + 50 ,@height]
@drawable.draw_line(@gc, *from, *to)
end
end
# 背景を黄色で描画
def clear
@gc.set_foreground(COLOR_DICT[:yellow])
@drawable.draw_rectangle(@gc, true, 0, 0, @width, @height)
end
private
# ウィンドウの出現位置を散らすため
def box_muller(m = [0, 0], s = [1, 1])
r1 = rand
r2 = rand
x = sqrt(-2 * log(r1)) * cos(2*PI * r2)
y = sqrt(-2 * log(r1)) * sin(2*PI * r2)
[s[0] * x + m[0], s[1] * y + m[1]]
end
end
wins = []
Gtk.timeout_add(100) do
wins << WarningWindow.new
wins.last.show_all
# たまにどれか消える
if rand < 0.3
win = wins.sample
win.destroy
wins.delete(win)
end
# MAXを越えたらこれ以上ウィンドウは増えない
if wins.size > MAX
sleep 1
wins.each(&:add_task)
true
end.!
end
begin
Gtk.main
rescue Interrupt
Gtk.main_quit
end
add_task メソッド内は指定した数のウィンドウが全て出力し終わったら定期的に実行される処理です(最後に縞模様を流してるのはそれっぽい演出のつもりです)。その中の self.move(@x, @y)
のコメントアウトを外すと以下のように画面内をウィンドウがごちゃごちゃ動き回るようになります。
おわりに
これを使えば誰でも、なんか攻撃を受けてるハッカーごっこができます。また、突然画面を隠さないといけない時などにも便利です。
GTKについてはまだあまり詳しくないので、ご意見ご指摘等ありましたらよろしくお願いします。