From 6ee42349bc488cbe08df833cabcdbc2f19c020d0 Mon Sep 17 00:00:00 2001 From: qlli Date: Fri, 18 Oct 2024 09:42:36 +0800 Subject: [PATCH] Type definition for sprite (#338) --- .gitignore | 1 - camera.go | 6 +- event.go | 29 ++-- game.go | 103 +++++++------- gop.mod | 3 + quote.go | 8 +- say.go | 8 +- spgdi.go | 24 ++-- sprite.go | 398 ++++++++++++++++++++++++++++++++--------------------- 9 files changed, 347 insertions(+), 233 deletions(-) create mode 100644 gop.mod diff --git a/.gitignore b/.gitignore index a15b02ea..96d1fdb2 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ .DS_Store sprite.txt game.txt -gop.mod go.work go.json gop.json diff --git a/camera.go b/camera.go index 54f24654..7f49ec1b 100644 --- a/camera.go +++ b/camera.go @@ -68,9 +68,9 @@ func (c *Camera) On(obj interface{}) { return } obj = sp - case *Sprite: + case *SpriteImpl: case nil: - case Spriter: + case Sprite: obj = spriteOf(v) case specialObj: if v != Mouse { @@ -85,7 +85,7 @@ func (c *Camera) On(obj interface{}) { func (c *Camera) updateOnObj() { switch v := c.on_.(type) { - case *Sprite: + case *SpriteImpl: cx, cy := v.getXY() c.freecamera.MoveTo(cx, cy) case nil: diff --git a/event.go b/event.go index 540cb4d9..3a77da6e 100644 --- a/event.go +++ b/event.go @@ -159,30 +159,30 @@ func (p *eventSinkMgr) doWhenClick(this threadObj) { }) } -func (p *eventSinkMgr) doWhenTouchStart(this threadObj, obj *Sprite) { +func (p *eventSinkMgr) doWhenTouchStart(this threadObj, obj *SpriteImpl) { p.allWhenTouchStart.asyncCall(false, this, func(ev *eventSink) { if debugEvent { log.Println("===> onTouchStart", nameOf(this), obj.name) } - ev.sink.(func(*Sprite))(obj) + ev.sink.(func(Sprite))(obj.sprite) }) } -func (p *eventSinkMgr) doWhenTouching(this threadObj, obj *Sprite) { +func (p *eventSinkMgr) doWhenTouching(this threadObj, obj *SpriteImpl) { p.allWhenTouching.asyncCall(false, this, func(ev *eventSink) { if debugEvent { log.Println("==> onTouching", nameOf(this), obj.name) } - ev.sink.(func(*Sprite))(obj) + ev.sink.(func(Sprite))(obj.sprite) }) } -func (p *eventSinkMgr) doWhenTouchEnd(this threadObj, obj *Sprite) { +func (p *eventSinkMgr) doWhenTouchEnd(this threadObj, obj *SpriteImpl) { p.allWhenTouchEnd.asyncCall(false, this, func(ev *eventSink) { if debugEvent { log.Println("===> onTouchEnd", nameOf(this), obj.name) } - ev.sink.(func(*Sprite))(obj) + ev.sink.(func(Sprite))(obj.sprite) }) } @@ -220,6 +220,19 @@ func (p *eventSinkMgr) doWhenBackdropChanged(name string, wait bool) { } // ------------------------------------------------------------------------------------- +type IEventSinks interface { + OnAnyKey(onKey func(key Key)) + OnBackdrop__0(onBackdrop func(name string)) + OnBackdrop__1(name string, onBackdrop func()) + OnClick(onClick func()) + OnKey__0(key Key, onKey func()) + OnKey__1(keys []Key, onKey func(Key)) + OnKey__2(keys []Key, onKey func()) + OnMsg__0(onMsg func(msg string, data interface{})) + OnMsg__1(msg string, onMsg func()) + OnStart(onStart func()) + Stop(kind StopKind) +} type eventSinks struct { *eventSinkMgr @@ -227,7 +240,7 @@ type eventSinks struct { } func nameOf(this interface{}) string { - if spr, ok := this.(*Sprite); ok { + if spr, ok := this.(*SpriteImpl); ok { return spr.name } if _, ok := this.(*Game); ok { @@ -423,7 +436,7 @@ func isGame(obj threadObj) bool { } func isSprite(obj threadObj) bool { - _, ok := obj.(*Sprite) + _, ok := obj.(*SpriteImpl) return ok } diff --git a/game.go b/game.go index f744d832..0ee16967 100644 --- a/game.go +++ b/game.go @@ -84,7 +84,7 @@ type Game struct { sounds soundMgr turtle turtleCanvas typs map[string]reflect.Type // map: name => sprite type, for all sprites - sprs map[string]Spriter // map: name => sprite prototype, for loaded sprites + sprs map[string]Sprite // map: name => sprite prototype, for loaded sprites items []Shape // shapes on stage (in Zorder), not only sprites tickMgr tickMgr @@ -109,12 +109,8 @@ type Game struct { isRunned bool } -type Spriter interface { - Shape - Main() -} type Gamer interface { - initGame(sprites []Spriter) *Game + initGame(sprites []Sprite) *Game } func (p *Game) IsRunned() bool { @@ -128,8 +124,8 @@ func (p *Game) getSharedImgs() *sharedImages { return p.shared } -func (p *Game) newSpriteAndLoad(name string, tySpr reflect.Type, g reflect.Value) Spriter { - spr := reflect.New(tySpr).Interface().(Spriter) +func (p *Game) newSpriteAndLoad(name string, tySpr reflect.Type, g reflect.Value) Sprite { + spr := reflect.New(tySpr).Interface().(Sprite) if err := p.loadSprite(spr, name, g); err != nil { panic(err) } @@ -137,7 +133,7 @@ func (p *Game) newSpriteAndLoad(name string, tySpr reflect.Type, g reflect.Value return spr } -func (p *Game) getSpriteProto(tySpr reflect.Type, g reflect.Value) Spriter { +func (p *Game) getSpriteProto(tySpr reflect.Type, g reflect.Value) Sprite { name := tySpr.Name() spr, ok := p.sprs[name] if !ok { @@ -146,7 +142,7 @@ func (p *Game) getSpriteProto(tySpr reflect.Type, g reflect.Value) Spriter { return spr } -func (p *Game) getSpriteProtoByName(name string, g reflect.Value) Spriter { +func (p *Game) getSpriteProtoByName(name string, g reflect.Value) Sprite { spr, ok := p.sprs[name] if !ok { tySpr, ok := p.typs[name] @@ -164,17 +160,17 @@ func (p *Game) reset() { p.Stop(AllOtherScripts) p.items = nil p.isLoaded = false - p.sprs = make(map[string]Spriter) + p.sprs = make(map[string]Sprite) } func (p *Game) getGame() *Game { return p } -func (p *Game) initGame(sprites []Spriter) *Game { +func (p *Game) initGame(sprites []Sprite) *Game { p.tickMgr.init() p.eventSinks.init(&p.sinkMgr, p) - p.sprs = make(map[string]Spriter) + p.sprs = make(map[string]Sprite) p.typs = make(map[string]reflect.Type) for _, spr := range sprites { tySpr := reflect.TypeOf(spr).Elem() @@ -184,7 +180,7 @@ func (p *Game) initGame(sprites []Spriter) *Game { } // Gopt_Game_Main is required by Go+ compiler as the entry of a .gmx project. -func Gopt_Game_Main(game Gamer, sprites ...Spriter) { +func Gopt_Game_Main(game Gamer, sprites ...Sprite) { g := game.initGame(sprites) if me, ok := game.(interface{ MainEntry() }); ok { me.MainEntry() @@ -257,7 +253,7 @@ func Gopt_Game_Run(game Gamer, resource interface{}, gameConf ...*Config) { } g.startLoad(fs, &conf) for i, n := 0, v.NumField(); i < n; i++ { - name, val := getFieldPtrOrAlloc(v, i) + name, val := getFieldPtrOrAlloc(g, v, i) switch fld := val.(type) { case *Sound: if g.canBindSound(name) { @@ -267,7 +263,7 @@ func Gopt_Game_Run(game Gamer, resource interface{}, gameConf ...*Config) { } *fld = media } - case Spriter: + case Sprite: if g.canBindSprite(name) { if err := g.loadSprite(fld, name, v); err != nil { panic(err) @@ -286,12 +282,12 @@ func Gopt_Game_Run(game Gamer, resource interface{}, gameConf ...*Config) { } // MouseHitItem returns the topmost item which is hit by mouse. -func (p *Game) MouseHitItem() (target *Sprite, ok bool) { +func (p *Game) MouseHitItem() (target *SpriteImpl, ok bool) { x, y := p.input.mouseXY() hc := hitContext{Pos: image.Pt(x, y)} item, ok := p.onHit(hc) if ok { - target, ok = item.Target.(*Sprite) + target, ok = item.Target.(*SpriteImpl) } return } @@ -304,17 +300,26 @@ func instance(gamer reflect.Value) *Game { return fld.Addr().Interface().(*Game) } -func getFieldPtrOrAlloc(v reflect.Value, i int) (name string, val interface{}) { +func getFieldPtrOrAlloc(g *Game, v reflect.Value, i int) (name string, val interface{}) { tFld := v.Type().Field(i) vFld := v.Field(i) typ := tFld.Type word := unsafe.Pointer(vFld.Addr().Pointer()) ret := reflect.NewAt(typ, word).Interface() - if vFld.Kind() == reflect.Ptr && typ.Implements(tySpriter) { + + if vFld.Kind() == reflect.Ptr && typ.Implements(tySprite) { obj := reflect.New(typ.Elem()) reflect.ValueOf(ret).Elem().Set(obj) ret = obj.Interface() } + + if vFld.Kind() == reflect.Interface && typ.Implements(tySprite) { + if typ2, ok := g.typs[tFld.Name]; ok { + obj := reflect.New(typ2) + reflect.ValueOf(ret).Elem().Set(obj) + ret = obj.Interface() + } + } return tFld.Name, ret } @@ -341,6 +346,10 @@ func findObjPtr(v reflect.Value, name string, from int) interface{} { word := unsafe.Pointer(vFld.Pointer()) return reflect.NewAt(typ.Elem(), word).Interface() } + if vFld.Kind() == reflect.Interface { + word := unsafe.Pointer(vFld.Addr().Pointer()) + return reflect.NewAt(tFld.Type, word).Elem().Interface() + } word := unsafe.Pointer(vFld.Addr().Pointer()) return reflect.NewAt(typ, word).Interface() } @@ -372,7 +381,7 @@ func (p *Game) canBindSprite(name string) bool { return true } -func (p *Game) loadSprite(sprite Spriter, name string, gamer reflect.Value) error { +func (p *Game) loadSprite(sprite Sprite, name string, gamer reflect.Value) error { if debugLoad { log.Println("==> LoadSprite", name) } @@ -386,8 +395,8 @@ func (p *Game) loadSprite(sprite Spriter, name string, gamer reflect.Value) erro // init sprite (field 0) vSpr := reflect.ValueOf(sprite).Elem() vSpr.Set(reflect.Zero(vSpr.Type())) - base := vSpr.Field(0).Addr().Interface().(*Sprite) - base.init(baseDir, p, name, &conf, gamer, p.getSharedImgs()) + base := vSpr.Field(0).Addr().Interface().(*SpriteImpl) + base.init(baseDir, p, name, &conf, gamer, p.getSharedImgs(), sprite) p.sprs[name] = sprite // // init gamer pointer (field 1) @@ -395,7 +404,7 @@ func (p *Game) loadSprite(sprite Spriter, name string, gamer reflect.Value) erro return nil } -func spriteOf(sprite Spriter) *Sprite { +func spriteOf(sprite Sprite) *SpriteImpl { vSpr := reflect.ValueOf(sprite) if vSpr.Kind() != reflect.Ptr { return nil @@ -405,10 +414,10 @@ func spriteOf(sprite Spriter) *Sprite { return nil } spriteField := vSpr.Field(0) - if spriteField.Type() != reflect.TypeOf(Sprite{}) { + if spriteField.Type() != reflect.TypeOf(SpriteImpl{}) { return nil } - return spriteField.Addr().Interface().(*Sprite) + return spriteField.Addr().Interface().(*SpriteImpl) } func (p *Game) loadIndex(g reflect.Value, proj *projConfig) (err error) { @@ -428,7 +437,7 @@ func (p *Game) loadIndex(g reflect.Value, proj *projConfig) (err error) { p.world = ebiten.NewImage(p.worldWidth_, p.worldHeight_) p.mapMode = toMapMode(proj.Map.Mode) - inits := make([]Spriter, 0, len(proj.Zorder)) + inits := make([]Sprite, 0, len(proj.Zorder)) for _, v := range proj.Zorder { if name, ok := v.(string); ok { sp := p.getSpriteProtoByName(name, g) @@ -486,8 +495,8 @@ func Gopt_Game_Reload(game Gamer, index interface{}) (err error) { g := instance(v) g.reset() for i, n := 0, v.NumField(); i < n; i++ { - name, val := getFieldPtrOrAlloc(v, i) - if fld, ok := val.(Spriter); ok { + name, val := getFieldPtrOrAlloc(g, v, i) + if fld, ok := val.(Sprite); ok { if err := g.loadSprite(fld, name, v); err != nil { panic(err) } @@ -504,7 +513,7 @@ func Gopt_Game_Reload(game Gamer, index interface{}) (err error) { type specsp = map[string]interface{} -func (p *Game) addSpecialShape(g reflect.Value, v specsp, inits []Spriter) []Spriter { +func (p *Game) addSpecialShape(g reflect.Value, v specsp, inits []Sprite) []Sprite { switch typ := v["type"].(string); typ { case "stageMonitor", "monitor": if sm, err := newMonitor(g, v); err == nil { @@ -523,10 +532,10 @@ func (p *Game) addSpecialShape(g reflect.Value, v specsp, inits []Spriter) []Spr return inits } -func (p *Game) addStageSprite(g reflect.Value, v specsp, inits []Spriter) []Spriter { +func (p *Game) addStageSprite(g reflect.Value, v specsp, inits []Sprite) []Sprite { target := v["target"].(string) if val := findObjPtr(g, target, 0); val != nil { - if sp, ok := val.(Spriter); ok { + if sp, ok := val.(Sprite); ok { dest := spriteOf(sp) applySpriteProps(dest, v) p.addShape(dest) @@ -553,7 +562,7 @@ func (p *Game) addStageSprite(g reflect.Value, v specsp, inits []Spriter) []Spri ] } */ -func (p *Game) addStageSprites(g reflect.Value, v specsp, inits []Spriter) []Spriter { +func (p *Game) addStageSprites(g reflect.Value, v specsp, inits []Sprite) []Sprite { target := v["target"].(string) if val := findFieldPtr(g, target, 0); val != nil { fldSlice := reflect.ValueOf(val).Elem() @@ -567,7 +576,7 @@ func (p *Game) addStageSprites(g reflect.Value, v specsp, inits []Spriter) []Spr } else { typItemPtr = reflect.PtrTo(typItem) } - if typItemPtr.Implements(tySpriter) { + if typItemPtr.Implements(tySprite) { spr := p.getSpriteProto(typItem, g) items := v["items"].([]interface{}) n := len(items) @@ -591,7 +600,7 @@ func (p *Game) addStageSprites(g reflect.Value, v specsp, inits []Spriter) []Spr } var ( - tySpriter = reflect.TypeOf((*Spriter)(nil)).Elem() + tySprite = reflect.TypeOf((*Sprite)(nil)).Elem() ) // ----------------------------------------------------------------------------- @@ -638,11 +647,11 @@ func (p *Game) updateColliders() { items := p.items n := len(items) for i := 0; i < n; i++ { - s1, ok1 := items[i].(*Sprite) + s1, ok1 := items[i].(*SpriteImpl) if ok1 { flag := s1.isVisible && !s1.isDying for j := i + 1; j < n; j++ { - s2, ok2 := items[j].(*Sprite) + s2, ok2 := items[j].(*SpriteImpl) if ok2 && s1 != s2 { flag2 := flag && s2.isVisible && !s2.isDying && s1.touchingSprite(s2) s1.collider.SetTouching(s2, flag2) @@ -827,17 +836,17 @@ func (p *Game) doWorldSize() { } } -func (p *Game) touchingPoint(dst *Sprite, x, y float64) bool { +func (p *Game) touchingPoint(dst *SpriteImpl, x, y float64) bool { return dst.touchPoint(x, y) } -func (p *Game) touchingSpriteBy(dst *Sprite, name string) *Sprite { +func (p *Game) touchingSpriteBy(dst *SpriteImpl, name string) *SpriteImpl { if dst == nil { return nil } for _, item := range p.items { - if sp, ok := item.(*Sprite); ok && sp != dst { + if sp, ok := item.(*SpriteImpl); ok && sp != dst { if sp.name == name && (sp.isVisible && !sp.isDying) { if sp.touchingSprite(dst) { return sp @@ -866,7 +875,7 @@ func (p *Game) objectPos(obj interface{}) (float64, float64) { mx, my := rand.Intn(worldW), rand.Intn(worldH) return float64(mx - (worldW >> 1)), float64((worldH >> 1) - my) } - case Spriter: + case Sprite: return spriteOf(v).getXY() } panic("objectPos: unexpected input") @@ -882,7 +891,7 @@ func (p *Game) stampCostume(di *spriteDrawInfo) { p.turtle.stampCostume(di) } -func (p *Game) movePen(sp *Sprite, x, y float64) { +func (p *Game) movePen(sp *SpriteImpl, x, y float64) { worldW, worldH := p.worldSize_() p.turtle.penLine(&penLine{ x1: (worldW >> 1) + int(sp.x), @@ -958,7 +967,7 @@ func (p *Game) activateShape(child Shape) { } } -func (p *Game) goBackByLayers(spr *Sprite, n int) { +func (p *Game) goBackByLayers(spr *SpriteImpl, n int) { idx := p.doFindSprite(spr) if idx < 0 { return @@ -969,7 +978,7 @@ func (p *Game) goBackByLayers(spr *Sprite, n int) { for newIdx > 0 { newIdx-- item := items[newIdx] - if _, ok := item.(*Sprite); ok { + if _, ok := item.(*SpriteImpl); ok { n-- if n == 0 { break @@ -995,7 +1004,7 @@ func (p *Game) goBackByLayers(spr *Sprite, n int) { break } item := items[newIdx] - if _, ok := item.(*Sprite); ok { + if _, ok := item.(*SpriteImpl); ok { n++ if n == 0 { break @@ -1024,9 +1033,9 @@ func (p *Game) doFindSprite(src Shape) int { return -1 } -func (p *Game) findSprite(name string) *Sprite { +func (p *Game) findSprite(name string) *SpriteImpl { for _, item := range p.items { - if sp, ok := item.(*Sprite); ok { + if sp, ok := item.(*SpriteImpl); ok { if !sp.isCloned_ && sp.name == name { return sp } diff --git a/gop.mod b/gop.mod new file mode 100644 index 00000000..10e8640b --- /dev/null +++ b/gop.mod @@ -0,0 +1,3 @@ +gop 1.3 +project .spx Game github.com/goplus/spx +class .spx SpriteImpl diff --git a/quote.go b/quote.go index caaa10ac..aa4376d3 100644 --- a/quote.go +++ b/quote.go @@ -55,14 +55,14 @@ func init() { } type quoter struct { - sprite *Sprite + sprite *SpriteImpl message string description string cachedImg *ebiten.Image } -func (p *Sprite) quote_(message, description string) { +func (p *SpriteImpl) quote_(message, description string) { old := p.quoteObj if old == nil { p.quoteObj = "er{sprite: p, message: message, description: description} @@ -74,12 +74,12 @@ func (p *Sprite) quote_(message, description string) { } } -func (p *Sprite) waitStopQuote(secs float64) { +func (p *SpriteImpl) waitStopQuote(secs float64) { p.g.Wait(secs) p.doStopQuote() } -func (p *Sprite) doStopQuote() { +func (p *SpriteImpl) doStopQuote() { if p.quoteObj != nil { p.g.removeShape(p.quoteObj) p.quoteObj = nil diff --git a/say.go b/say.go index 1054adf3..6641cb58 100644 --- a/say.go +++ b/say.go @@ -61,7 +61,7 @@ const ( ) type sayOrThinker struct { - sp *Sprite + sp *SpriteImpl msg string style int // styleSay, styleThink } @@ -180,7 +180,7 @@ func (p *sayOrThinker) hit(hc hitContext) (hr hitResult, ok bool) { // ------------------------------------------------------------------------------------- -func (p *Sprite) sayOrThink(msgv interface{}, style int) { +func (p *SpriteImpl) sayOrThink(msgv interface{}, style int) { msg, ok := msgv.(string) if !ok { msg = fmt.Sprint(msgv) @@ -201,12 +201,12 @@ func (p *Sprite) sayOrThink(msgv interface{}, style int) { } } -func (p *Sprite) waitStopSay(secs float64) { +func (p *SpriteImpl) waitStopSay(secs float64) { p.g.Wait(secs) p.doStopSay() } -func (p *Sprite) doStopSay() { +func (p *SpriteImpl) doStopSay() { if p.sayObj != nil { p.g.removeShape(p.sayObj) p.sayObj = nil diff --git a/spgdi.go b/spgdi.go index 6eae5f10..8f5c5a82 100644 --- a/spgdi.go +++ b/spgdi.go @@ -54,7 +54,7 @@ type Shape interface { // ------------------------------------------------------------------------------------- type spriteDrawInfo struct { - sprite *Sprite + sprite *SpriteImpl geo ebiten.GeoM visible bool } @@ -100,7 +100,7 @@ func (p *spriteDrawInfo) drawOn(dc drawContext, fs spxfs.Dir) { p.doDrawOn(dc, fs) } -func (p *spriteDrawInfo) draw(dc drawContext, ctx *Sprite) { +func (p *spriteDrawInfo) draw(dc drawContext, ctx *SpriteImpl) { p.doDrawOn(dc, ctx.g.fs) } @@ -207,14 +207,14 @@ func (p *spriteDrawInfo) doDrawOn(dc drawContext, fs spxfs.Dir) { } } -func (p *Sprite) getDrawInfo() *spriteDrawInfo { +func (p *SpriteImpl) getDrawInfo() *spriteDrawInfo { return &spriteDrawInfo{ sprite: p, visible: p.isVisible, } } -func (p *Sprite) touchPoint(x, y float64) bool { +func (p *SpriteImpl) touchPoint(x, y float64) bool { rRect := p.getRotatedRect() if rRect == nil { return false @@ -239,7 +239,7 @@ func (p *Sprite) touchPoint(x, y float64) bool { return true } -func (p *Sprite) touchRotatedRect(dstRect *math32.RotatedRect) bool { +func (p *SpriteImpl) touchRotatedRect(dstRect *math32.RotatedRect) bool { currRect := p.getRotatedRect() if currRect == nil { return false @@ -275,7 +275,7 @@ func (p *Sprite) touchRotatedRect(dstRect *math32.RotatedRect) bool { return false } -func (p *Sprite) touchedColor_(dst *Sprite, color Color) bool { +func (p *SpriteImpl) touchedColor_(dst *SpriteImpl, color Color) bool { currRect := p.getRotatedRect() if currRect == nil { return false @@ -321,7 +321,7 @@ func (p *Sprite) touchedColor_(dst *Sprite, color Color) bool { return false } -func (p *Sprite) touchingSprite(dst *Sprite) bool { +func (p *SpriteImpl) touchingSprite(dst *SpriteImpl) bool { currRect := p.getRotatedRect() if currRect == nil { return false @@ -369,7 +369,7 @@ func (p *Sprite) touchingSprite(dst *Sprite) bool { return false } -func (p *Sprite) getRotatedRect() (rRect *math32.RotatedRect) { +func (p *SpriteImpl) getRotatedRect() (rRect *math32.RotatedRect) { di := p.getDrawInfo() if !di.visible { return @@ -378,7 +378,7 @@ func (p *Sprite) getRotatedRect() (rRect *math32.RotatedRect) { return } -func (p *Sprite) getTrackPos() (topx, topy int) { +func (p *SpriteImpl) getTrackPos() (topx, topy int) { rRect := p.getRotatedRect() if rRect == nil { return @@ -399,7 +399,7 @@ func (p *Sprite) getTrackPos() (topx, topy int) { return int(pos.X), int(pos.Y) - int(rRect.Size.Height)/2 } -func (p *Sprite) draw(dc drawContext) { +func (p *SpriteImpl) draw(dc drawContext) { di := p.getDrawInfo() if !di.visible { return @@ -408,7 +408,7 @@ func (p *Sprite) draw(dc drawContext) { } // Hit func. -func (p *Sprite) hit(hc hitContext) (hr hitResult, ok bool) { +func (p *SpriteImpl) hit(hc hitContext) (hr hitResult, ok bool) { rRect := p.getRotatedRect() if rRect == nil { return @@ -439,7 +439,7 @@ func (p *Sprite) hit(hc hitContext) (hr hitResult, ok bool) { return hitResult{Target: p}, true } -func (p *Sprite) applyPivot(c *costume, cx, cy *float64) { +func (p *SpriteImpl) applyPivot(c *costume, cx, cy *float64) { *cx += p.pivot.X * float64(c.bitmapResolution) *cy -= p.pivot.Y * float64(c.bitmapResolution) } diff --git a/sprite.go b/sprite.go index aad9da07..337c1a71 100644 --- a/sprite.go +++ b/sprite.go @@ -62,12 +62,12 @@ const ( ) type Collider struct { - sprite *Sprite - others map[*Sprite]bool + sprite *SpriteImpl + others map[*SpriteImpl]bool othersM sync.Mutex } -func (c *Collider) SetTouching(other *Sprite, on bool) { +func (c *Collider) SetTouching(other *SpriteImpl, on bool) { c.othersM.Lock() defer c.othersM.Unlock() @@ -76,7 +76,7 @@ func (c *Collider) SetTouching(other *Sprite, on bool) { } if c.others == nil { - c.others = make(map[*Sprite]bool) + c.others = make(map[*SpriteImpl]bool) } _, exist := c.others[other] @@ -96,7 +96,7 @@ func (c *Collider) SetTouching(other *Sprite, on bool) { } func (c *Collider) Reset() { - copy := make(map[*Sprite]bool, len(c.others)) + copy := make(map[*SpriteImpl]bool, len(c.others)) for k, v := range c.others { copy[k] = v } @@ -106,12 +106,101 @@ func (c *Collider) Reset() { } } -type Sprite struct { +type Sprite interface { + IEventSinks + Shape + Main() + + Animate(name string) + Ask(msg interface{}) + BounceOffEdge() + Bounds() *math32.RotatedRect + ChangeEffect(kind EffectKind, delta float64) + ChangeHeading(dir float64) + ChangePenColor(delta float64) + ChangePenHue(delta float64) + ChangePenShade(delta float64) + ChangePenSize(delta float64) + ChangeSize(delta float64) + ChangeXpos(dx float64) + ChangeXYpos(dx, dy float64) + ChangeYpos(dy float64) + ClearGraphEffects() + CostumeHeight() float64 + CostumeIndex() int + CostumeName() string + CostumeWidth() float64 + DeleteThisClone() + Destroy() + Die() + DistanceTo(obj interface{}) float64 + Glide__0(x, y float64, secs float64) + Glide__1(obj interface{}, secs float64) + GoBackLayers(n int) + Goto(obj interface{}) + GotoBack() + GotoFront() + Heading() float64 + Hide() + HideVar(name string) + IsCloned() bool + Move__0(step float64) + Move__1(step int) + NextCostume() + OnCloned__0(onCloned func(data interface{})) + OnCloned__1(onCloned func()) + OnMoving__0(onMoving func(mi *MovingInfo)) + OnMoving__1(onMoving func()) + OnTouchStart__0(onTouchStart func(Sprite)) + OnTouchStart__1(onTouchStart func()) + OnTouchStart__2(name string, onTouchStart func(Sprite)) + OnTouchStart__3(name string, onTouchStart func()) + OnTurning__0(onTurning func(ti *TurningInfo)) + OnTurning__1(onTurning func()) + Parent() *Game + PenDown() + PenUp() + PrevCostume() + Quote__0(message string) + Quote__1(message string, secs float64) + Quote__2(message, description string, secs ...float64) + Say(msg interface{}, secs ...float64) + SetCostume(costume interface{}) + SetDying() + SetEffect(kind EffectKind, val float64) + SetHeading(dir float64) + SetPenColor(color Color) + SetPenHue(hue float64) + SetPenShade(shade float64) + SetPenSize(size float64) + SetRotationStyle(style RotationStyle) + SetSize(size float64) + SetXpos(x float64) + SetXYpos(x, y float64) + SetYpos(y float64) + Show() + ShowVar(name string) + Size() float64 + Stamp() + Step__0(step float64) + Step__1(step int) + Step__2(step float64, animname string) + Think(msg interface{}, secs ...float64) + Touching(obj interface{}) bool + TouchingColor(color Color) bool + Turn(val interface{}) + TurnTo(obj interface{}) + Visible() bool + Xpos() float64 + Ypos() float64 +} + +type SpriteImpl struct { baseObj eventSinks - g *Game - - name string + g *Game + sprite Sprite + name string x, y float64 scale float64 @@ -152,45 +241,45 @@ type Sprite struct { collider Collider } -func (p *Sprite) SetDying() { // dying: visible but can't be touched +func (p *SpriteImpl) SetDying() { // dying: visible but can't be touched p.isDying = true } -func (p *Sprite) Parent() *Game { +func (p *SpriteImpl) Parent() *Game { return p.g } -func (p *Sprite) getAllShapes() []Shape { +func (p *SpriteImpl) getAllShapes() []Shape { return p.g.getAllShapes() } -func (p *Sprite) init( - base string, g *Game, name string, sprite *spriteConfig, gamer reflect.Value, shared *sharedImages) { - if sprite.Costumes != nil { - p.baseObj.init(base, sprite.Costumes, sprite.getCostumeIndex()) +func (p *SpriteImpl) init( + base string, g *Game, name string, spriteCfg *spriteConfig, gamer reflect.Value, shared *sharedImages, sprite Sprite) { + if spriteCfg.Costumes != nil { + p.baseObj.init(base, spriteCfg.Costumes, spriteCfg.getCostumeIndex()) } else { - p.baseObj.initWith(base, sprite, shared) + p.baseObj.initWith(base, spriteCfg, shared) } p.defaultCostumeIndex = p.baseObj.costumeIndex_ p.eventSinks.init(&g.sinkMgr, p) p.gamer = gamer - p.g, p.name = g, name - p.x, p.y = sprite.X, sprite.Y - p.scale = sprite.Size - p.direction = sprite.Heading - p.rotationStyle = toRotationStyle(sprite.RotationStyle) - p.isVisible = sprite.Visible - p.pivot = sprite.Pivot + p.g, p.name, p.sprite = g, name, sprite + p.x, p.y = spriteCfg.X, spriteCfg.Y + p.scale = spriteCfg.Size + p.direction = spriteCfg.Heading + p.rotationStyle = toRotationStyle(spriteCfg.RotationStyle) + p.isVisible = spriteCfg.Visible + p.pivot = spriteCfg.Pivot p.animBindings = make(map[string]string) - for key, val := range sprite.AnimBindings { + for key, val := range spriteCfg.AnimBindings { p.animBindings[key] = val } - p.defaultAnimation = sprite.DefaultAnimation + p.defaultAnimation = spriteCfg.DefaultAnimation p.animations = make(map[string]*aniConfig) - for key, val := range sprite.FAnimations { + for key, val := range spriteCfg.FAnimations { var ani = val _, ok := p.animations[key] if ok { @@ -248,7 +337,7 @@ func (p *Sprite) init( p.animations[key] = ani } - for key, val := range sprite.MAnimations { + for key, val := range spriteCfg.MAnimations { _, ok := p.animations[key] if ok { log.Panicf("animation key [%s] is exist", key) @@ -261,7 +350,7 @@ func (p *Sprite) init( p.animations[key] = ani } - for key, val := range sprite.TAnimations { + for key, val := range spriteCfg.TAnimations { _, ok := p.animations[key] if ok { log.Panicf("animation key [%s] is exist", key) @@ -274,15 +363,14 @@ func (p *Sprite) init( p.animations[key] = ani } - p.collider.others = make(map[*Sprite]bool) + p.collider.others = make(map[*SpriteImpl]bool) p.collider.sprite = p } - -func (p *Sprite) awake() { +func (p *SpriteImpl) awake() { p.playDefaultAnim() } -func (p *Sprite) InitFrom(src *Sprite) { +func (p *SpriteImpl) InitFrom(src *SpriteImpl) { p.baseObj.initFrom(&src.baseObj) p.eventSinks.initFrom(&src.eventSinks, p) @@ -312,7 +400,7 @@ func (p *Sprite) InitFrom(src *Sprite) { p.hasOnTouching = false p.hasOnTouchEnd = false - p.collider.others = make(map[*Sprite]bool) + p.collider.others = make(map[*SpriteImpl]bool) p.collider.sprite = p } @@ -333,7 +421,7 @@ func applyFloat64(out *float64, in interface{}) { } } -func applySpriteProps(dest *Sprite, v specsp) { +func applySpriteProps(dest *SpriteImpl, v specsp) { applyFloat64(&dest.x, v["x"]) applyFloat64(&dest.y, v["y"]) applyFloat64(&dest.scale, v["size"]) @@ -354,13 +442,13 @@ func applySpriteProps(dest *Sprite, v specsp) { dest.isCloned_ = false } -func applySprite(out reflect.Value, sprite Spriter, v specsp) (*Sprite, Spriter) { +func applySprite(out reflect.Value, sprite Sprite, v specsp) (*SpriteImpl, Sprite) { in := reflect.ValueOf(sprite).Elem() - outPtr := out.Addr().Interface().(Spriter) + outPtr := out.Addr().Interface().(Sprite) return cloneSprite(out, outPtr, in, v), outPtr } -func cloneSprite(out reflect.Value, outPtr Spriter, in reflect.Value, v specsp) *Sprite { +func cloneSprite(out reflect.Value, outPtr Sprite, in reflect.Value, v specsp) *SpriteImpl { dest := spriteOf(outPtr) func() { out.Set(in) @@ -372,6 +460,7 @@ func cloneSprite(out reflect.Value, outPtr Spriter, in reflect.Value, v specsp) } } }() + dest.sprite = outPtr if v != nil { // in loadSprite applySpriteProps(dest, v) } else { // in sprite.Clone @@ -383,18 +472,18 @@ func cloneSprite(out reflect.Value, outPtr Spriter, in reflect.Value, v specsp) return dest } -func Gopt_Sprite_Clone__0(sprite Spriter) { - Gopt_Sprite_Clone__1(sprite, nil) +func Gopt_SpriteImpl_Clone__0(sprite Sprite) { + Gopt_SpriteImpl_Clone__1(sprite, nil) } -func Gopt_Sprite_Clone__1(sprite Spriter, data interface{}) { +func Gopt_SpriteImpl_Clone__1(sprite Sprite, data interface{}) { src := spriteOf(sprite) if debugInstr { log.Println("Clone", src.name) } in := reflect.ValueOf(sprite).Elem() v := reflect.New(in.Type()) - out, outPtr := v.Elem(), v.Interface().(Spriter) + out, outPtr := v.Elem(), v.Interface().(Sprite) dest := cloneSprite(out, outPtr, in, nil) src.g.addClonedShape(src, dest) if dest.hasOnCloned { @@ -402,7 +491,7 @@ func Gopt_Sprite_Clone__1(sprite Spriter, data interface{}) { } } -func (p *Sprite) OnCloned__0(onCloned func(data interface{})) { +func (p *SpriteImpl) OnCloned__0(onCloned func(data interface{})) { p.hasOnCloned = true p.allWhenCloned = &eventSink{ prev: p.allWhenCloned, @@ -414,31 +503,31 @@ func (p *Sprite) OnCloned__0(onCloned func(data interface{})) { } } -func (p *Sprite) OnCloned__1(onCloned func()) { +func (p *SpriteImpl) OnCloned__1(onCloned func()) { p.OnCloned__0(func(interface{}) { onCloned() }) } -func (p *Sprite) fireTouchStart(obj *Sprite) { +func (p *SpriteImpl) fireTouchStart(obj *SpriteImpl) { if p.hasOnTouchStart { p.doWhenTouchStart(p, obj) } } -func (p *Sprite) fireTouching(obj *Sprite) { +func (p *SpriteImpl) fireTouching(obj *SpriteImpl) { if p.hasOnTouching { p.doWhenTouching(p, obj) } } -func (p *Sprite) fireTouchEnd(obj *Sprite) { +func (p *SpriteImpl) fireTouchEnd(obj *SpriteImpl) { if p.hasOnTouchEnd { p.doWhenTouchEnd(p, obj) } } -func (p *Sprite) OnTouchStart__0(onTouchStart func(obj *Sprite)) { +func (p *SpriteImpl) OnTouchStart__0(onTouchStart func(Sprite)) { p.hasOnTouchStart = true p.allWhenTouchStart = &eventSink{ prev: p.allWhenTouchStart, @@ -450,22 +539,23 @@ func (p *Sprite) OnTouchStart__0(onTouchStart func(obj *Sprite)) { } } -func (p *Sprite) OnTouchStart__1(onTouchStart func()) { - p.OnTouchStart__0(func(*Sprite) { +func (p *SpriteImpl) OnTouchStart__1(onTouchStart func()) { + p.OnTouchStart__0(func(Sprite) { onTouchStart() }) } -func (p *Sprite) OnTouchStart__2(name string, onTouchStart func(*Sprite)) { - p.OnTouchStart__0(func(obj *Sprite) { - if obj.name == name { - onTouchStart(obj) +func (p *SpriteImpl) OnTouchStart__2(name string, onTouchStart func(Sprite)) { + p.OnTouchStart__0(func(sprite Sprite) { + impl := spriteOf(sprite) + if impl != nil && impl.name == name { + onTouchStart(sprite) } }) } -func (p *Sprite) OnTouchStart__3(name string, onTouchStart func()) { - p.OnTouchStart__2(name, func(*Sprite) { +func (p *SpriteImpl) OnTouchStart__3(name string, onTouchStart func()) { + p.OnTouchStart__2(name, func(Sprite) { onTouchStart() }) } @@ -474,7 +564,7 @@ type MovingInfo struct { OldX, OldY float64 NewX, NewY float64 ani *anim.Anim - Obj *Sprite + Obj *SpriteImpl } func (p *MovingInfo) StopMoving() { @@ -491,7 +581,7 @@ func (p *MovingInfo) Dy() float64 { return p.NewY - p.OldY } -func (p *Sprite) OnMoving__0(onMoving func(mi *MovingInfo)) { +func (p *SpriteImpl) OnMoving__0(onMoving func(mi *MovingInfo)) { p.hasOnMoving = true p.allWhenMoving = &eventSink{ prev: p.allWhenMoving, @@ -503,7 +593,7 @@ func (p *Sprite) OnMoving__0(onMoving func(mi *MovingInfo)) { } } -func (p *Sprite) OnMoving__1(onMoving func()) { +func (p *SpriteImpl) OnMoving__1(onMoving func()) { p.OnMoving__0(func(mi *MovingInfo) { onMoving() }) @@ -512,14 +602,14 @@ func (p *Sprite) OnMoving__1(onMoving func()) { type TurningInfo struct { OldDir float64 NewDir float64 - Obj *Sprite + Obj *SpriteImpl } func (p *TurningInfo) Dir() float64 { return p.NewDir - p.OldDir } -func (p *Sprite) OnTurning__0(onTurning func(ti *TurningInfo)) { +func (p *SpriteImpl) OnTurning__0(onTurning func(ti *TurningInfo)) { p.hasOnTurning = true p.allWhenTurning = &eventSink{ prev: p.allWhenTurning, @@ -531,13 +621,13 @@ func (p *Sprite) OnTurning__0(onTurning func(ti *TurningInfo)) { } } -func (p *Sprite) OnTurning__1(onTurning func()) { +func (p *SpriteImpl) OnTurning__1(onTurning func()) { p.OnTurning__0(func(*TurningInfo) { onTurning() }) } -func (p *Sprite) Die() { +func (p *SpriteImpl) Die() { aniName := p.getStateAnimName(StateDie) p.SetDying() @@ -549,7 +639,7 @@ func (p *Sprite) Die() { p.Destroy() } -func (p *Sprite) Destroy() { // destroy sprite, whether prototype or cloned +func (p *SpriteImpl) Destroy() { // destroy sprite, whether prototype or cloned if debugInstr { log.Println("Destroy", p.name) } @@ -566,7 +656,7 @@ func (p *Sprite) Destroy() { // destroy sprite, whether prototype or cloned // delete only cloned sprite, no effect on prototype sprite. // Add this interface, to match Scratch. -func (p *Sprite) DeleteThisClone() { +func (p *SpriteImpl) DeleteThisClone() { if !p.isCloned_ { return } @@ -574,7 +664,7 @@ func (p *Sprite) DeleteThisClone() { p.Destroy() } -func (p *Sprite) Hide() { +func (p *SpriteImpl) Hide() { if debugInstr { log.Println("Hide", p.name) } @@ -584,32 +674,32 @@ func (p *Sprite) Hide() { p.isVisible = false } -func (p *Sprite) Show() { +func (p *SpriteImpl) Show() { if debugInstr { log.Println("Show", p.name) } p.isVisible = true } -func (p *Sprite) Visible() bool { +func (p *SpriteImpl) Visible() bool { return p.isVisible } -func (p *Sprite) IsCloned() bool { +func (p *SpriteImpl) IsCloned() bool { return p.isCloned_ } // ----------------------------------------------------------------------------- -func (p *Sprite) CostumeName() string { +func (p *SpriteImpl) CostumeName() string { return p.getCostumeName() } -func (p *Sprite) CostumeIndex() int { +func (p *SpriteImpl) CostumeIndex() int { return p.getCostumeIndex() } -func (p *Sprite) SetCostume(costume interface{}) { +func (p *SpriteImpl) SetCostume(costume interface{}) { if debugInstr { log.Println("SetCostume", p.name, costume) } @@ -617,7 +707,7 @@ func (p *Sprite) SetCostume(costume interface{}) { p.defaultCostumeIndex = p.costumeIndex_ } -func (p *Sprite) NextCostume() { +func (p *SpriteImpl) NextCostume() { if debugInstr { log.Println("NextCostume", p.name) } @@ -625,7 +715,7 @@ func (p *Sprite) NextCostume() { p.defaultCostumeIndex = p.costumeIndex_ } -func (p *Sprite) PrevCostume() { +func (p *SpriteImpl) PrevCostume() { if debugInstr { log.Println("PrevCostume", p.name) } @@ -635,7 +725,7 @@ func (p *Sprite) PrevCostume() { // ----------------------------------------------------------------------------- -func (p *Sprite) getFromAnToForAni(anitype aniTypeEnum, from interface{}, to interface{}) (interface{}, interface{}) { +func (p *SpriteImpl) getFromAnToForAni(anitype aniTypeEnum, from interface{}, to interface{}) (interface{}, interface{}) { if anitype == aniTypeFrame { return p.getFromAnToForAniFrames(from, to) @@ -645,7 +735,7 @@ func (p *Sprite) getFromAnToForAni(anitype aniTypeEnum, from interface{}, to int } -func (p *Sprite) getFromAnToForAniFrames(from interface{}, to interface{}) (float64, float64) { +func (p *SpriteImpl) getFromAnToForAniFrames(from interface{}, to interface{}) (float64, float64) { fromval := 0.0 toval := 0.0 switch v := from.(type) { @@ -671,7 +761,7 @@ func (p *Sprite) getFromAnToForAniFrames(from interface{}, to interface{}) (floa return fromval, toval } -func (p *Sprite) getStateAnimName(stateName string) string { +func (p *SpriteImpl) getStateAnimName(stateName string) string { if bindingName, ok := p.animBindings[stateName]; ok { return bindingName } @@ -681,10 +771,10 @@ func (p *Sprite) getStateAnimName(stateName string) string { func lerp(a float64, b float64, progress float64) float64 { return a + (b-a)*progress } -func (p *Sprite) goAnimate(name string, ani *aniConfig) { +func (p *SpriteImpl) goAnimate(name string, ani *aniConfig) { p.goAnimateInternal(name, ani, true) } -func (p *Sprite) goAnimateInternal(name string, ani *aniConfig, isBlocking bool) { +func (p *SpriteImpl) goAnimateInternal(name string, ani *aniConfig, isBlocking bool) { if p.lastAnim != nil { p.isWaitingStopAnim = true p.lastAnim.Stop() @@ -857,7 +947,7 @@ func (p *Sprite) goAnimateInternal(name string, ani *aniConfig, isBlocking bool) } } -func (p *Sprite) Animate(name string) { +func (p *SpriteImpl) Animate(name string) { if debugInstr { log.Println("==> Animation", name) } @@ -870,11 +960,11 @@ func (p *Sprite) Animate(name string) { // ----------------------------------------------------------------------------- -func (p *Sprite) Ask(msg interface{}) { +func (p *SpriteImpl) Ask(msg interface{}) { panic("todo") } -func (p *Sprite) Say(msg interface{}, secs ...float64) { +func (p *SpriteImpl) Say(msg interface{}, secs ...float64) { if debugInstr { log.Println("Say", p.name, msg, secs) } @@ -884,7 +974,7 @@ func (p *Sprite) Say(msg interface{}, secs ...float64) { } } -func (p *Sprite) Think(msg interface{}, secs ...float64) { +func (p *SpriteImpl) Think(msg interface{}, secs ...float64) { if debugInstr { log.Println("Think", p.name, msg, secs) } @@ -894,7 +984,7 @@ func (p *Sprite) Think(msg interface{}, secs ...float64) { } } -func (p *Sprite) Quote__0(message string) { +func (p *SpriteImpl) Quote__0(message string) { if message == "" { p.doStopQuote() return @@ -902,11 +992,11 @@ func (p *Sprite) Quote__0(message string) { p.Quote__2(message, "") } -func (p *Sprite) Quote__1(message string, secs float64) { +func (p *SpriteImpl) Quote__1(message string, secs float64) { p.Quote__2(message, "", secs) } -func (p *Sprite) Quote__2(message, description string, secs ...float64) { +func (p *SpriteImpl) Quote__2(message, description string, secs ...float64) { if debugInstr { log.Println("Quote", p.name, message, description, secs) } @@ -918,7 +1008,7 @@ func (p *Sprite) Quote__2(message, description string, secs ...float64) { // ----------------------------------------------------------------------------- -func (p *Sprite) getXY() (x, y float64) { +func (p *SpriteImpl) getXY() (x, y float64) { return p.x, p.y } @@ -928,7 +1018,7 @@ func (p *Sprite) getXY() (x, y float64) { // DistanceTo(spriteName) // DistanceTo(spx.Mouse) // DistanceTo(spx.Random) -func (p *Sprite) DistanceTo(obj interface{}) float64 { +func (p *SpriteImpl) DistanceTo(obj interface{}) float64 { x, y := p.x, p.y x2, y2 := p.g.objectPos(obj) x -= x2 @@ -936,11 +1026,11 @@ func (p *Sprite) DistanceTo(obj interface{}) float64 { return math.Sqrt(x*x + y*y) } -func (p *Sprite) doMoveTo(x, y float64) { +func (p *SpriteImpl) doMoveTo(x, y float64) { p.doMoveToForAnim(x, y, nil) } -func (p *Sprite) doMoveToForAnim(x, y float64, ani *anim.Anim) { +func (p *SpriteImpl) doMoveToForAnim(x, y float64, ani *anim.Anim) { x, y = p.fixWorldRange(x, y) if p.hasOnMoving { mi := &MovingInfo{OldX: p.x, OldY: p.y, NewX: x, NewY: y, Obj: p, ani: ani} @@ -953,32 +1043,32 @@ func (p *Sprite) doMoveToForAnim(x, y float64, ani *anim.Anim) { p.getDrawInfo().updateMatrix() } -func (p *Sprite) goMoveForward(step float64) { +func (p *SpriteImpl) goMoveForward(step float64) { sin, cos := math.Sincos(toRadian(p.direction)) p.doMoveTo(p.x+step*sin, p.y+step*cos) } -func (p *Sprite) Move__0(step float64) { +func (p *SpriteImpl) Move__0(step float64) { if debugInstr { log.Println("Move", p.name, step) } p.goMoveForward(step) } -func (p *Sprite) Move__1(step int) { +func (p *SpriteImpl) Move__1(step int) { p.Move__0(float64(step)) } -func (p *Sprite) Step__0(step float64) { +func (p *SpriteImpl) Step__0(step float64) { animName := p.getStateAnimName(StateStep) p.Step__2(step, animName) } -func (p *Sprite) Step__1(step int) { +func (p *SpriteImpl) Step__1(step int) { p.Step__0(float64(step)) } -func (p *Sprite) Step__2(step float64, animname string) { +func (p *SpriteImpl) Step__2(step float64, animname string) { if debugInstr { log.Println("Step", p.name, step) } @@ -995,7 +1085,7 @@ func (p *Sprite) Step__2(step float64, animname string) { p.goMoveForward(step) } -func (p *Sprite) playDefaultAnim() { +func (p *SpriteImpl) playDefaultAnim() { animName := p.defaultAnimation if p.isVisible { isPlayAnim := false @@ -1020,7 +1110,7 @@ func (p *Sprite) playDefaultAnim() { // Goto(spriteName) // Goto(spx.Mouse) // Goto(spx.Random) -func (p *Sprite) Goto(obj interface{}) { +func (p *SpriteImpl) Goto(obj interface{}) { if debugInstr { log.Println("Goto", p.name, obj) } @@ -1028,7 +1118,7 @@ func (p *Sprite) Goto(obj interface{}) { p.SetXYpos(x, y) } -func (p *Sprite) Glide__0(x, y float64, secs float64) { +func (p *SpriteImpl) Glide__0(x, y float64, secs float64) { if debugInstr { log.Println("Glide", p.name, x, y, secs) } @@ -1044,7 +1134,7 @@ func (p *Sprite) Glide__0(x, y float64, secs float64) { p.goAnimate(animName, ani) } -func (p *Sprite) Glide__1(obj interface{}, secs float64) { +func (p *SpriteImpl) Glide__1(obj interface{}, secs float64) { if debugInstr { log.Println("Glide", obj, secs) } @@ -1052,35 +1142,35 @@ func (p *Sprite) Glide__1(obj interface{}, secs float64) { p.Glide__0(x, y, secs) } -func (p *Sprite) SetXYpos(x, y float64) { +func (p *SpriteImpl) SetXYpos(x, y float64) { p.doMoveTo(x, y) } -func (p *Sprite) ChangeXYpos(dx, dy float64) { +func (p *SpriteImpl) ChangeXYpos(dx, dy float64) { p.doMoveTo(p.x+dx, p.y+dy) } -func (p *Sprite) Xpos() float64 { +func (p *SpriteImpl) Xpos() float64 { return p.x } -func (p *Sprite) SetXpos(x float64) { +func (p *SpriteImpl) SetXpos(x float64) { p.doMoveTo(x, p.y) } -func (p *Sprite) ChangeXpos(dx float64) { +func (p *SpriteImpl) ChangeXpos(dx float64) { p.doMoveTo(p.x+dx, p.y) } -func (p *Sprite) Ypos() float64 { +func (p *SpriteImpl) Ypos() float64 { return p.y } -func (p *Sprite) SetYpos(y float64) { +func (p *SpriteImpl) SetYpos(y float64) { p.doMoveTo(p.x, y) } -func (p *Sprite) ChangeYpos(dy float64) { +func (p *SpriteImpl) ChangeYpos(dy float64) { p.doMoveTo(p.x, p.y+dy) } @@ -1104,14 +1194,14 @@ func toRotationStyle(style string) RotationStyle { return Normal } -func (p *Sprite) SetRotationStyle(style RotationStyle) { +func (p *SpriteImpl) SetRotationStyle(style RotationStyle) { if debugInstr { log.Println("SetRotationStyle", p.name, style) } p.rotationStyle = style } -func (p *Sprite) Heading() float64 { +func (p *SpriteImpl) Heading() float64 { return p.direction } @@ -1121,7 +1211,7 @@ func (p *Sprite) Heading() float64 { // Turn(spx.Left) // Turn(spx.Right) // Turn(ti *spx.TurningInfo) -func (p *Sprite) Turn(val interface{}) { +func (p *SpriteImpl) Turn(val interface{}) { var delta float64 switch v := val.(type) { //case specialDir: @@ -1160,7 +1250,7 @@ func (p *Sprite) Turn(val interface{}) { // TurnTo(spx.Right) // TurnTo(spx.Up) // TurnTo(spx.Down) -func (p *Sprite) TurnTo(obj interface{}) { +func (p *SpriteImpl) TurnTo(obj interface{}) { var angle float64 switch v := obj.(type) { //case specialDir: @@ -1200,15 +1290,15 @@ func (p *Sprite) TurnTo(obj interface{}) { } } -func (p *Sprite) SetHeading(dir float64) { +func (p *SpriteImpl) SetHeading(dir float64) { p.setDirection(dir, false) } -func (p *Sprite) ChangeHeading(dir float64) { +func (p *SpriteImpl) ChangeHeading(dir float64) { p.setDirection(dir, true) } -func (p *Sprite) setDirection(dir float64, change bool) bool { +func (p *SpriteImpl) setDirection(dir float64, change bool) bool { if change { dir += p.direction } @@ -1224,7 +1314,7 @@ func (p *Sprite) setDirection(dir float64, change bool) bool { return true } -func (p *Sprite) doTurnTogether(ti *TurningInfo) { +func (p *SpriteImpl) doTurnTogether(ti *TurningInfo) { /* x’ = x0 + cos * (x-x0) + sin * (y-y0) y’ = y0 - sin * (x-x0) + cos * (y-y0) @@ -1238,12 +1328,12 @@ func (p *Sprite) doTurnTogether(ti *TurningInfo) { // ----------------------------------------------------------------------------- -func (p *Sprite) Size() float64 { +func (p *SpriteImpl) Size() float64 { v := p.scale return v } -func (p *Sprite) SetSize(size float64) { +func (p *SpriteImpl) SetSize(size float64) { if debugInstr { log.Println("SetSize", p.name, size) } @@ -1251,7 +1341,7 @@ func (p *Sprite) SetSize(size float64) { p.getDrawInfo().updateMatrix() } -func (p *Sprite) ChangeSize(delta float64) { +func (p *SpriteImpl) ChangeSize(delta float64) { if debugInstr { log.Println("ChangeSize", p.name, delta) } @@ -1261,7 +1351,7 @@ func (p *Sprite) ChangeSize(delta float64) { // ----------------------------------------------------------------------------- -func (p *Sprite) requireGreffUniforms() map[string]interface{} { +func (p *SpriteImpl) requireGreffUniforms() map[string]interface{} { effs := p.greffUniforms if effs == nil { effs = make(map[string]interface{}) @@ -1270,12 +1360,12 @@ func (p *Sprite) requireGreffUniforms() map[string]interface{} { return effs } -func (p *Sprite) SetEffect(kind EffectKind, val float64) { +func (p *SpriteImpl) SetEffect(kind EffectKind, val float64) { effs := p.requireGreffUniforms() effs[kind.String()] = float32(val) } -func (p *Sprite) ChangeEffect(kind EffectKind, delta float64) { +func (p *SpriteImpl) ChangeEffect(kind EffectKind, delta float64) { effs := p.requireGreffUniforms() key := kind.String() newVal := float32(delta) @@ -1285,7 +1375,7 @@ func (p *Sprite) ChangeEffect(kind EffectKind, delta float64) { effs[key] = newVal } -func (p *Sprite) ClearGraphEffects() { +func (p *SpriteImpl) ClearGraphEffects() { p.greffUniforms = nil } @@ -1293,9 +1383,9 @@ func (p *Sprite) ClearGraphEffects() { type Color = color.RGBA -func (p *Sprite) TouchingColor(color Color) bool { +func (p *SpriteImpl) TouchingColor(color Color) bool { for _, item := range p.g.items { - if sp, ok := item.(*Sprite); ok && sp != p { + if sp, ok := item.(*SpriteImpl); ok && sp != p { ret := p.touchedColor_(sp, color) if ret { return true @@ -1315,7 +1405,7 @@ func (p *Sprite) TouchingColor(color Color) bool { // Touching(spx.EdgeTop) // Touching(spx.EdgeRight) // Touching(spx.EdgeBottom) -func (p *Sprite) Touching(obj interface{}) bool { +func (p *SpriteImpl) Touching(obj interface{}) bool { if !p.isVisible || p.isDying { return false } @@ -1332,13 +1422,13 @@ func (p *Sprite) Touching(obj interface{}) bool { x, y := p.g.getMousePos() return p.g.touchingPoint(p, x, y) } - case Spriter: + case Sprite: return touchingSprite(p, spriteOf(v)) } panic("Touching: unexpected input") } -func touchingSprite(dst, src *Sprite) bool { +func touchingSprite(dst, src *SpriteImpl) bool { if !src.isVisible || src.isDying { return false } @@ -1354,7 +1444,7 @@ const ( touchingAllEdges = 15 ) -func (p *Sprite) BounceOffEdge() { +func (p *SpriteImpl) BounceOffEdge() { if debugInstr { log.Println("BounceOffEdge", p.name) } @@ -1398,7 +1488,7 @@ func checkTouchingDirection(dir float64) int { return touchingScreenTop } -func (p *Sprite) checkTouchingScreen(where int) (touching int) { +func (p *SpriteImpl) checkTouchingScreen(where int) (touching int) { rect := p.getRotatedRect() if rect == nil { return @@ -1444,60 +1534,60 @@ func (p *Sprite) checkTouchingScreen(where int) (touching int) { // ----------------------------------------------------------------------------- -func (p *Sprite) GoBackLayers(n int) { +func (p *SpriteImpl) GoBackLayers(n int) { p.g.goBackByLayers(p, n) } -func (p *Sprite) GotoFront() { +func (p *SpriteImpl) GotoFront() { p.g.goBackByLayers(p, -1e8) } -func (p *Sprite) GotoBack() { +func (p *SpriteImpl) GotoBack() { p.g.goBackByLayers(p, 1e8) } // ----------------------------------------------------------------------------- -func (p *Sprite) Stamp() { +func (p *SpriteImpl) Stamp() { p.g.stampCostume(p.getDrawInfo()) } -func (p *Sprite) PenUp() { +func (p *SpriteImpl) PenUp() { p.isPenDown = false } -func (p *Sprite) PenDown() { +func (p *SpriteImpl) PenDown() { p.isPenDown = true } -func (p *Sprite) SetPenColor(color Color) { +func (p *SpriteImpl) SetPenColor(color Color) { h, _, v := clrutil.RGB2HSV(color.R, color.G, color.B) p.penHue = (200 * h) / 360 p.penShade = 50 * v p.penColor = color } -func (p *Sprite) ChangePenColor(delta float64) { +func (p *SpriteImpl) ChangePenColor(delta float64) { panic("todo") } -func (p *Sprite) SetPenShade(shade float64) { +func (p *SpriteImpl) SetPenShade(shade float64) { p.setPenShade(shade, false) } -func (p *Sprite) ChangePenShade(delta float64) { +func (p *SpriteImpl) ChangePenShade(delta float64) { p.setPenShade(delta, true) } -func (p *Sprite) SetPenHue(hue float64) { +func (p *SpriteImpl) SetPenHue(hue float64) { p.setPenHue(hue, false) } -func (p *Sprite) ChangePenHue(delta float64) { +func (p *SpriteImpl) ChangePenHue(delta float64) { p.setPenHue(delta, true) } -func (p *Sprite) setPenHue(v float64, change bool) { +func (p *SpriteImpl) setPenHue(v float64, change bool) { if change { v += p.penHue } @@ -1509,7 +1599,7 @@ func (p *Sprite) setPenHue(v float64, change bool) { p.doUpdatePenColor() } -func (p *Sprite) setPenShade(v float64, change bool) { +func (p *SpriteImpl) setPenShade(v float64, change bool) { if change { v += p.penShade } @@ -1521,7 +1611,7 @@ func (p *Sprite) setPenShade(v float64, change bool) { p.doUpdatePenColor() } -func (p *Sprite) doUpdatePenColor() { +func (p *SpriteImpl) doUpdatePenColor() { r, g, b := clrutil.HSV2RGB((p.penHue*180)/100, 1, 1) shade := p.penShade if shade > 100 { // range 0..100 @@ -1535,15 +1625,15 @@ func (p *Sprite) doUpdatePenColor() { p.penColor = color.RGBA{R: r, G: g, B: b, A: p.penColor.A} } -func (p *Sprite) SetPenSize(size float64) { +func (p *SpriteImpl) SetPenSize(size float64) { p.setPenWidth(size, true) } -func (p *Sprite) ChangePenSize(delta float64) { +func (p *SpriteImpl) ChangePenSize(delta float64) { p.setPenWidth(delta, true) } -func (p *Sprite) setPenWidth(w float64, change bool) { +func (p *SpriteImpl) setPenWidth(w float64, change bool) { if change { w += p.penWidth } @@ -1552,18 +1642,18 @@ func (p *Sprite) setPenWidth(w float64, change bool) { // ----------------------------------------------------------------------------- -func (p *Sprite) HideVar(name string) { +func (p *SpriteImpl) HideVar(name string) { p.g.setStageMonitor(p.name, getVarPrefix+name, false) } -func (p *Sprite) ShowVar(name string) { +func (p *SpriteImpl) ShowVar(name string) { p.g.setStageMonitor(p.name, getVarPrefix+name, true) } // ----------------------------------------------------------------------------- // CostumeWidth returns width of sprite current costume. -func (p *Sprite) CostumeWidth() float64 { +func (p *SpriteImpl) CostumeWidth() float64 { c := p.costumes[p.costumeIndex_] img, _, _ := c.needImage(p.g.fs) w, _ := img.Size() @@ -1571,14 +1661,14 @@ func (p *Sprite) CostumeWidth() float64 { } // CostumeHeight returns height of sprite current costume. -func (p *Sprite) CostumeHeight() float64 { +func (p *SpriteImpl) CostumeHeight() float64 { c := p.costumes[p.costumeIndex_] img, _, _ := c.needImage(p.g.fs) _, h := img.Size() return float64(h / c.bitmapResolution) } -func (p *Sprite) Bounds() *math32.RotatedRect { +func (p *SpriteImpl) Bounds() *math32.RotatedRect { return p.getRotatedRect() } @@ -1597,7 +1687,7 @@ func (p *Sprite) Bounds() *math32.RotatedRect { // ----------------------------------------------------------------------------- -func (p *Sprite) fixWorldRange(x, y float64) (float64, float64) { +func (p *SpriteImpl) fixWorldRange(x, y float64) (float64, float64) { rect := p.getDrawInfo().getUpdateRotateRect(x, y) if rect == nil { return x, y