火曜日, 11月 09, 2010

Gordonさまがマウスカーソルにくっつく

多少書き直してみた。ついでに分身の術ではなく、マウスカーソルにくっつくように動くようにした。
コールバックな部分は若干やっつけだけど、基本的にはこんな感じだと思う。
event.goは綺麗というかすっきりして、ここまで来たらファイルを分離する意味が無い。
その分、main.goのhandleMouseEventがやたら汚い。
interface{}を具体的な型に落とす方法はswitchしかないのかな。

(一度投降後、何度かコードを綺麗にしてます)

main.go

package main

import (
"fmt"
"exp/draw"
"exp/draw/x11"
"image"

"./event"
"./gordon"
)

func handleMouseEvent(event interface{}, args ...interface{}) {
switch e := event.(type) {
case draw.MouseEvent:
{
me := draw.MouseEvent(e)
switch win := args[0].(type) {
case draw.Window:
{
win = draw.Window(win)
switch char := args[1].(type) {
case gordon.Character:
{
char = gordon.Character(char)
fmt.Printf(
"MouseEvent: Button= %d, Loc= %v\n",
me.Buttons, me.Loc)

draw.Draw(win.Screen(), char.Canon(), char.Mask(), image.ZP)
char.Position(me.Loc.X, me.Loc.Y)
draw.Draw(win.Screen(), char.Canon(), char, image.ZP)
win.FlushImage()
}
}
}
}
}
}
}

func main() {
gordon1, e := gordon.NewGordon(image.Point{X: 0, Y: 0})
if e != nil {
fmt.Printf("Error %v\n", e)
return
}

win, e := x11.NewWindow()
if e != nil {
fmt.Printf("Error %v\n", e)
return
}

eventChan := win.EventChan()
mouseCallBack := event.CallBack(handleMouseEvent)
sync := make(<-chan bool)
go event.HandleCallBack(eventChan, mouseCallBack, win, gordon1)
<-sync
}

event.go

package event

type CallBack func(event interface{}, args ...interface{})

func HandleCallBack(eventChan <-chan interface{}, fun CallBack, args ...interface{}) {
for {
event := <-eventChan
go fun(event, args...)
}
}

gordon.go

package gordon

import (
"bufio"
"image"
"image/png"
"os"
)
os.DevNull

type Character interface {
image.Image
Canon() image.Rectangle
Mask() image.Image
Position(x, y int)
}

type Gordon struct {
image.Image
Rect image.Rectangle
maskImage image.Image
}

func (g *Gordon) Position(x, y int) {
r := g.Bounds()
g.Rect = image.Rect(
x, y,
x+r.Max.X, y+r.Max.Y)
}

func (g *Gordon) Canon() image.Rectangle {
return g.Rect.Canon()
}

func (g *Gordon) Mask() image.Image {
return g.maskImage
}

func NewGordon(point image.Point) (gordon *Gordon, e os.Error) {
gordon = new(Gordon)
img, e := loadGordon()
if e != nil {
return nil, e
}
gordon.Image = img
gordon.Position(point.X, point.Y)
gordon.maskImage = image.NewGray(img.Bounds().Max.X, img.Bounds().Max.Y)
return gordon, e
}

func loadGordon() (image.Image, os.Error) {
file, e := os.Open("./Gordon.png", os.O_RDONLY, 0666)
if e != nil {
return nil, e
}

read := bufio.NewReader(file)
icon, e := png.Decode(read)
if e != nil {
return nil, e
}
return icon, nil
}

0 件のコメント: