From 90750d09af543a7fcc698b8bb00b0b8d0193a86e Mon Sep 17 00:00:00 2001 From: qlli Date: Sun, 29 Sep 2024 15:49:06 +0800 Subject: [PATCH 1/9] fix: Strange behavior of OnTouched #298 --- event.go | 24 +++++++++++++ game.go | 35 +++++++++++++++++- sprite.go | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 157 insertions(+), 6 deletions(-) diff --git a/event.go b/event.go index 30ebafbd..8d1ca041 100644 --- a/event.go +++ b/event.go @@ -94,7 +94,9 @@ type eventSinkMgr struct { allWhenIReceive *eventSink allWhenBackdropChanged *eventSink allWhenCloned *eventSink + allWhenTouchBegin *eventSink allWhenTouched *eventSink + allWhenTouchEnd *eventSink allWhenClick *eventSink allWhenMoving *eventSink allWhenTurning *eventSink @@ -107,7 +109,9 @@ func (p *eventSinkMgr) reset() { p.allWhenIReceive = nil p.allWhenBackdropChanged = nil p.allWhenCloned = nil + p.allWhenTouchBegin = nil p.allWhenTouched = nil + p.allWhenTouchEnd = nil p.allWhenClick = nil p.allWhenMoving = nil p.allWhenTurning = nil @@ -120,7 +124,9 @@ func (p *eventSinkMgr) doDeleteClone(this interface{}) { p.allWhenIReceive = p.allWhenIReceive.doDeleteClone(this) p.allWhenBackdropChanged = p.allWhenBackdropChanged.doDeleteClone(this) p.allWhenCloned = p.allWhenCloned.doDeleteClone(this) + p.allWhenTouchBegin = p.allWhenTouchBegin.doDeleteClone(this) p.allWhenTouched = p.allWhenTouched.doDeleteClone(this) + p.allWhenTouchEnd = p.allWhenTouchEnd.doDeleteClone(this) p.allWhenClick = p.allWhenClick.doDeleteClone(this) p.allWhenMoving = p.allWhenMoving.doDeleteClone(this) p.allWhenTurning = p.allWhenTurning.doDeleteClone(this) @@ -153,6 +159,15 @@ func (p *eventSinkMgr) doWhenClick(this threadObj) { }) } +func (p *eventSinkMgr) doWhenTouchBegin(this threadObj, obj *Sprite) { + p.allWhenTouchBegin.asyncCall(false, this, func(ev *eventSink) { + if debugEvent { + log.Println("===> onTouchBegin", nameOf(this), obj.name) + } + ev.sink.(func(*Sprite))(obj) + }) +} + func (p *eventSinkMgr) doWhenTouched(this threadObj, obj *Sprite) { p.allWhenTouched.asyncCall(false, this, func(ev *eventSink) { if debugEvent { @@ -162,6 +177,15 @@ func (p *eventSinkMgr) doWhenTouched(this threadObj, obj *Sprite) { }) } +func (p *eventSinkMgr) doWhenTouchEnd(this threadObj, obj *Sprite) { + p.allWhenTouchEnd.asyncCall(false, this, func(ev *eventSink) { + if debugEvent { + log.Println("===> onTouchEnd", nameOf(this), obj.name) + } + ev.sink.(func(*Sprite))(obj) + }) +} + func (p *eventSinkMgr) doWhenCloned(this threadObj, data interface{}) { p.allWhenCloned.asyncCall(true, this, func(ev *eventSink) { if debugEvent { diff --git a/game.go b/game.go index 407cbb4e..f744d832 100644 --- a/game.go +++ b/game.go @@ -53,19 +53,22 @@ const ( DbgFlagLoad dbgFlags = 1 << iota DbgFlagInstr DbgFlagEvent - DbgFlagAll = DbgFlagLoad | DbgFlagInstr | DbgFlagEvent + DbgFlagPerf + DbgFlagAll = DbgFlagLoad | DbgFlagInstr | DbgFlagEvent | DbgFlagPerf ) var ( debugInstr bool debugLoad bool debugEvent bool + debugPerf bool ) func SetDebug(flags dbgFlags) { debugLoad = (flags & DbgFlagLoad) != 0 debugInstr = (flags & DbgFlagInstr) != 0 debugEvent = (flags & DbgFlagEvent) != 0 + debugPerf = (flags & DbgFlagPerf) != 0 } // ------------------------------------------------------------------------------------- @@ -617,6 +620,8 @@ func (p *Game) Update() error { if !p.isLoaded { return nil } + + p.updateColliders() p.input.update() p.updateMousePos() p.sounds.update() @@ -624,6 +629,34 @@ func (p *Game) Update() error { return nil } +func (p *Game) updateColliders() { + var startTime time.Time + if debugPerf { + startTime = time.Now() + } + + items := p.items + n := len(items) + for i := 0; i < n; i++ { + s1, ok1 := items[i].(*Sprite) + if ok1 { + flag := s1.isVisible && !s1.isDying + for j := i + 1; j < n; j++ { + s2, ok2 := items[j].(*Sprite) + if ok2 && s1 != s2 { + flag2 := flag && s2.isVisible && !s2.isDying && s1.touchingSprite(s2) + s1.collider.SetTouching(s2, flag2) + s2.collider.SetTouching(s1, flag2) + } + } + } + } + + if debugPerf { + log.Println("updateColliders shapes:", n, " cost:", time.Now().Sub(startTime)) + } +} + // startTick creates tickHandler to handle `onTick` event. // You can call tickHandler.Stop to stop listening `onTick` event. func (p *Game) startTick(duration int64, onTick func(tick int64)) *tickHandler { diff --git a/sprite.go b/sprite.go index fb0c89ef..cc5decc2 100644 --- a/sprite.go +++ b/sprite.go @@ -17,10 +17,12 @@ package spx import ( + "fmt" "image/color" "log" "math" "reflect" + "runtime" "sync" "github.com/goplus/spx/internal/anim" @@ -61,6 +63,47 @@ const ( AnimChannelMove string = "@move" ) +type Collider struct { + sprite *Sprite + others map[*Sprite]bool +} + +func (c *Collider) SetTouching(other *Sprite, on bool) { + if other == nil || c.sprite == nil { + return + } + + if c.others == nil { + c.others = make(map[*Sprite]bool) + } + + _, exist := c.others[other] + if on { + if !exist { + c.others[other] = true + c.sprite.fireTouchBegin(other) + } else { + c.sprite.fireTouched(other) + } + } else { + if exist { + delete(c.others, other) // shared container in multiple goroutines, any problem? + c.sprite.fireTouchEnd(other) + } + } +} + +func (c *Collider) Reset() { + copy := make(map[*Sprite]bool, len(c.others)) + for k, v := range c.others { + copy[k] = v + } + for other := range copy { + c.SetTouching(other, false) + other.collider.SetTouching(c.sprite, false) + } +} + type Sprite struct { baseObj eventSinks @@ -92,15 +135,19 @@ type Sprite struct { isPenDown bool isDying bool - hasOnTurning bool - hasOnMoving bool - hasOnCloned bool - hasOnTouched bool + hasOnTurning bool + hasOnMoving bool + hasOnCloned bool + hasOnTouchBegin bool + hasOnTouched bool + hasOnTouchEnd bool gamer reflect.Value lastAnim *anim.Anim isWaitingStopAnim bool defaultCostumeIndex int + + collider Collider } func (p *Sprite) SetDying() { // dying: visible but can't be touched @@ -224,7 +271,11 @@ func (p *Sprite) init( } p.animations[key] = ani } + + p.collider.others = make(map[*Sprite]bool) + p.collider.sprite = p } + func (p *Sprite) awake() { p.playDefaultAnim() } @@ -255,7 +306,12 @@ func (p *Sprite) InitFrom(src *Sprite) { p.hasOnTurning = false p.hasOnMoving = false p.hasOnCloned = false + p.hasOnTouchBegin = false p.hasOnTouched = false + p.hasOnTouchEnd = false + + p.collider.others = make(map[*Sprite]bool) + p.collider.sprite = p } func cloneMap(v map[string]interface{}) map[string]interface{} { @@ -362,12 +418,36 @@ func (p *Sprite) OnCloned__1(onCloned func()) { }) } +func (p *Sprite) fireTouchBegin(obj *Sprite) { + if p.hasOnTouchBegin { + p.doWhenTouchBegin(p, obj) + } +} + func (p *Sprite) fireTouched(obj *Sprite) { if p.hasOnTouched { p.doWhenTouched(p, obj) } } +func (p *Sprite) fireTouchEnd(obj *Sprite) { + if p.hasOnTouchEnd { + p.doWhenTouchEnd(p, obj) + } +} + +func (p *Sprite) OnTouchBegin(onTouchBegin func(obj *Sprite)) { + p.hasOnTouchBegin = true + p.allWhenTouchBegin = &eventSink{ + prev: p.allWhenTouchBegin, + pthis: p, + sink: onTouchBegin, + cond: func(data interface{}) bool { + return data == p + }, + } +} + func (p *Sprite) OnTouched__0(onTouched func(obj *Sprite)) { p.hasOnTouched = true p.allWhenTouched = &eventSink{ @@ -418,6 +498,18 @@ func (p *Sprite) OnTouched__5(names []string, onTouched func()) { }) } +func (p *Sprite) OnTouchEnd(onTouchEnd func(obj *Sprite)) { + p.hasOnTouchEnd = true + p.allWhenTouchEnd = &eventSink{ + prev: p.allWhenTouchEnd, + pthis: p, + sink: onTouchEnd, + cond: func(data interface{}) bool { + return data == p + }, + } +} + type MovingInfo struct { OldX, OldY float64 NewX, NewY float64 @@ -502,6 +594,7 @@ func (p *Sprite) Destroy() { // destroy sprite, whether prototype or cloned log.Println("Destroy", p.name) } + p.collider.Reset() p.Hide() p.doDeleteClone() p.g.removeShape(p) @@ -525,6 +618,8 @@ func (p *Sprite) Hide() { if debugInstr { log.Println("Hide", p.name) } + + p.collider.Reset() p.doStopSay() p.isVisible = false } @@ -1267,7 +1362,6 @@ func (p *Sprite) Touching(obj interface{}) bool { switch v := obj.(type) { case string: if o := p.g.touchingSpriteBy(p, v); o != nil { - o.fireTouched(p) return true } return false From 71173866046e1cfd0b17045c8995aba365f5ff2c Mon Sep 17 00:00:00 2001 From: qlli Date: Sun, 29 Sep 2024 16:01:46 +0800 Subject: [PATCH 2/9] Remove unused import --- sprite.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/sprite.go b/sprite.go index cc5decc2..7112293e 100644 --- a/sprite.go +++ b/sprite.go @@ -17,12 +17,10 @@ package spx import ( - "fmt" "image/color" "log" "math" "reflect" - "runtime" "sync" "github.com/goplus/spx/internal/anim" From 9952e6f4af05437a388ecb065b5590e732524f4e Mon Sep 17 00:00:00 2001 From: qlli Date: Mon, 30 Sep 2024 16:04:05 +0800 Subject: [PATCH 3/9] Rename onTouchBegin => onTouchStart --- event.go | 12 ++++++------ sprite.go | 22 +++++++++++----------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/event.go b/event.go index 8d1ca041..60d045e6 100644 --- a/event.go +++ b/event.go @@ -94,7 +94,7 @@ type eventSinkMgr struct { allWhenIReceive *eventSink allWhenBackdropChanged *eventSink allWhenCloned *eventSink - allWhenTouchBegin *eventSink + allWhenTouchStart *eventSink allWhenTouched *eventSink allWhenTouchEnd *eventSink allWhenClick *eventSink @@ -109,7 +109,7 @@ func (p *eventSinkMgr) reset() { p.allWhenIReceive = nil p.allWhenBackdropChanged = nil p.allWhenCloned = nil - p.allWhenTouchBegin = nil + p.allWhenTouchStart = nil p.allWhenTouched = nil p.allWhenTouchEnd = nil p.allWhenClick = nil @@ -124,7 +124,7 @@ func (p *eventSinkMgr) doDeleteClone(this interface{}) { p.allWhenIReceive = p.allWhenIReceive.doDeleteClone(this) p.allWhenBackdropChanged = p.allWhenBackdropChanged.doDeleteClone(this) p.allWhenCloned = p.allWhenCloned.doDeleteClone(this) - p.allWhenTouchBegin = p.allWhenTouchBegin.doDeleteClone(this) + p.allWhenTouchStart = p.allWhenTouchStart.doDeleteClone(this) p.allWhenTouched = p.allWhenTouched.doDeleteClone(this) p.allWhenTouchEnd = p.allWhenTouchEnd.doDeleteClone(this) p.allWhenClick = p.allWhenClick.doDeleteClone(this) @@ -159,10 +159,10 @@ func (p *eventSinkMgr) doWhenClick(this threadObj) { }) } -func (p *eventSinkMgr) doWhenTouchBegin(this threadObj, obj *Sprite) { - p.allWhenTouchBegin.asyncCall(false, this, func(ev *eventSink) { +func (p *eventSinkMgr) doWhenTouchStart(this threadObj, obj *Sprite) { + p.allWhenTouchStart.asyncCall(false, this, func(ev *eventSink) { if debugEvent { - log.Println("===> onTouchBegin", nameOf(this), obj.name) + log.Println("===> onTouchStart", nameOf(this), obj.name) } ev.sink.(func(*Sprite))(obj) }) diff --git a/sprite.go b/sprite.go index 7112293e..9ab66f81 100644 --- a/sprite.go +++ b/sprite.go @@ -79,7 +79,7 @@ func (c *Collider) SetTouching(other *Sprite, on bool) { if on { if !exist { c.others[other] = true - c.sprite.fireTouchBegin(other) + c.sprite.fireTouchStart(other) } else { c.sprite.fireTouched(other) } @@ -136,7 +136,7 @@ type Sprite struct { hasOnTurning bool hasOnMoving bool hasOnCloned bool - hasOnTouchBegin bool + hasOnTouchStart bool hasOnTouched bool hasOnTouchEnd bool @@ -304,7 +304,7 @@ func (p *Sprite) InitFrom(src *Sprite) { p.hasOnTurning = false p.hasOnMoving = false p.hasOnCloned = false - p.hasOnTouchBegin = false + p.hasOnTouchStart = false p.hasOnTouched = false p.hasOnTouchEnd = false @@ -416,9 +416,9 @@ func (p *Sprite) OnCloned__1(onCloned func()) { }) } -func (p *Sprite) fireTouchBegin(obj *Sprite) { - if p.hasOnTouchBegin { - p.doWhenTouchBegin(p, obj) +func (p *Sprite) fireTouchStart(obj *Sprite) { + if p.hasOnTouchStart { + p.doWhenTouchStart(p, obj) } } @@ -434,12 +434,12 @@ func (p *Sprite) fireTouchEnd(obj *Sprite) { } } -func (p *Sprite) OnTouchBegin(onTouchBegin func(obj *Sprite)) { - p.hasOnTouchBegin = true - p.allWhenTouchBegin = &eventSink{ - prev: p.allWhenTouchBegin, +func (p *Sprite) OnTouchStart(onTouchStart func(obj *Sprite)) { + p.hasOnTouchStart = true + p.allWhenTouchStart = &eventSink{ + prev: p.allWhenTouchStart, pthis: p, - sink: onTouchBegin, + sink: onTouchStart, cond: func(data interface{}) bool { return data == p }, From d15064072b911cc2f28708551e1a67caf2824d30 Mon Sep 17 00:00:00 2001 From: qlli Date: Mon, 30 Sep 2024 16:15:11 +0800 Subject: [PATCH 4/9] Remove touch interfaces of sprites --- sprite.go | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/sprite.go b/sprite.go index 9ab66f81..68346fc4 100644 --- a/sprite.go +++ b/sprite.go @@ -478,24 +478,6 @@ func (p *Sprite) OnTouched__3(name string, onTouched func()) { }) } -func (p *Sprite) OnTouched__4(names []string, onTouched func(obj *Sprite)) { - p.OnTouched__0(func(obj *Sprite) { - name := obj.name - for _, v := range names { - if v == name { - onTouched(obj) - return - } - } - }) -} - -func (p *Sprite) OnTouched__5(names []string, onTouched func()) { - p.OnTouched__4(names, func(*Sprite) { - onTouched() - }) -} - func (p *Sprite) OnTouchEnd(onTouchEnd func(obj *Sprite)) { p.hasOnTouchEnd = true p.allWhenTouchEnd = &eventSink{ From 4e5416500257ab93f45c9713a60ced3448598a1a Mon Sep 17 00:00:00 2001 From: qlli Date: Mon, 30 Sep 2024 16:24:26 +0800 Subject: [PATCH 5/9] Remove alert in comment --- sprite.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sprite.go b/sprite.go index 68346fc4..09c5a28c 100644 --- a/sprite.go +++ b/sprite.go @@ -85,7 +85,7 @@ func (c *Collider) SetTouching(other *Sprite, on bool) { } } else { if exist { - delete(c.others, other) // shared container in multiple goroutines, any problem? + delete(c.others, other) c.sprite.fireTouchEnd(other) } } From 2b81afae00f9c8b171b941a0dced048d5b1b33fd Mon Sep 17 00:00:00 2001 From: qlli Date: Tue, 8 Oct 2024 23:57:03 +0800 Subject: [PATCH 6/9] Add OnTouchStart interfaces, Remove OnTouched and OnTouchEnd --- sprite.go | 44 ++++++++++---------------------------------- 1 file changed, 10 insertions(+), 34 deletions(-) diff --git a/sprite.go b/sprite.go index 09c5a28c..8799931e 100644 --- a/sprite.go +++ b/sprite.go @@ -434,7 +434,7 @@ func (p *Sprite) fireTouchEnd(obj *Sprite) { } } -func (p *Sprite) OnTouchStart(onTouchStart func(obj *Sprite)) { +func (p *Sprite) OnTouchStart__0(onTouchStart func(obj *Sprite)) { p.hasOnTouchStart = true p.allWhenTouchStart = &eventSink{ prev: p.allWhenTouchStart, @@ -446,50 +446,26 @@ func (p *Sprite) OnTouchStart(onTouchStart func(obj *Sprite)) { } } -func (p *Sprite) OnTouched__0(onTouched func(obj *Sprite)) { - p.hasOnTouched = true - p.allWhenTouched = &eventSink{ - prev: p.allWhenTouched, - pthis: p, - sink: onTouched, - cond: func(data interface{}) bool { - return data == p - }, - } -} - -func (p *Sprite) OnTouched__1(onTouched func()) { - p.OnTouched__0(func(*Sprite) { - onTouched() +func (p *Sprite) OnTouchStart__1(onTouchStart func()) { + p.OnTouchStart__0(func(*Sprite) { + onTouchStart() }) } -func (p *Sprite) OnTouched__2(name string, onTouched func(obj *Sprite)) { - p.OnTouched__0(func(obj *Sprite) { +func (p *Sprite) OnTouchStart__2(name string, onTouchStart func(*Sprite)) { + p.OnTouchStart__0(func(obj *Sprite) { if obj.name == name { - onTouched(obj) + onTouchStart(obj) } }) } -func (p *Sprite) OnTouched__3(name string, onTouched func()) { - p.OnTouched__2(name, func(*Sprite) { - onTouched() +func (p *Sprite) OnTouchStart__3(name string, onTouchStart func()) { + p.OnTouchStart__2(name, func(*Sprite) { + onTouchStart() }) } -func (p *Sprite) OnTouchEnd(onTouchEnd func(obj *Sprite)) { - p.hasOnTouchEnd = true - p.allWhenTouchEnd = &eventSink{ - prev: p.allWhenTouchEnd, - pthis: p, - sink: onTouchEnd, - cond: func(data interface{}) bool { - return data == p - }, - } -} - type MovingInfo struct { OldX, OldY float64 NewX, NewY float64 From 70ba13d0133ac90c1c5320d112c17d8c34972e64 Mon Sep 17 00:00:00 2001 From: qlli Date: Wed, 9 Oct 2024 10:59:16 +0800 Subject: [PATCH 7/9] Fix data race in test case --- sprite.go | 8 ++++++-- tutorial/05-Animation/Bullet.spx | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/sprite.go b/sprite.go index 8799931e..d5d5843e 100644 --- a/sprite.go +++ b/sprite.go @@ -62,11 +62,15 @@ const ( ) type Collider struct { - sprite *Sprite - others map[*Sprite]bool + sprite *Sprite + others map[*Sprite]bool + othersM sync.Mutex } func (c *Collider) SetTouching(other *Sprite, on bool) { + c.othersM.Lock() + defer c.othersM.Unlock() + if other == nil || c.sprite == nil { return } diff --git a/tutorial/05-Animation/Bullet.spx b/tutorial/05-Animation/Bullet.spx index bce81ca6..49d1e943 100644 --- a/tutorial/05-Animation/Bullet.spx +++ b/tutorial/05-Animation/Bullet.spx @@ -1,4 +1,4 @@ -onTouched => { +onTouchStart => { destroy } From be21c8c96b2be4fb5fc181bfd23b871ebfb2df84 Mon Sep 17 00:00:00 2001 From: qlli Date: Wed, 9 Oct 2024 11:06:56 +0800 Subject: [PATCH 8/9] Rename *touched* to *touching* --- event.go | 12 ++++++------ sprite.go | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/event.go b/event.go index 60d045e6..540cb4d9 100644 --- a/event.go +++ b/event.go @@ -95,7 +95,7 @@ type eventSinkMgr struct { allWhenBackdropChanged *eventSink allWhenCloned *eventSink allWhenTouchStart *eventSink - allWhenTouched *eventSink + allWhenTouching *eventSink allWhenTouchEnd *eventSink allWhenClick *eventSink allWhenMoving *eventSink @@ -110,7 +110,7 @@ func (p *eventSinkMgr) reset() { p.allWhenBackdropChanged = nil p.allWhenCloned = nil p.allWhenTouchStart = nil - p.allWhenTouched = nil + p.allWhenTouching = nil p.allWhenTouchEnd = nil p.allWhenClick = nil p.allWhenMoving = nil @@ -125,7 +125,7 @@ func (p *eventSinkMgr) doDeleteClone(this interface{}) { p.allWhenBackdropChanged = p.allWhenBackdropChanged.doDeleteClone(this) p.allWhenCloned = p.allWhenCloned.doDeleteClone(this) p.allWhenTouchStart = p.allWhenTouchStart.doDeleteClone(this) - p.allWhenTouched = p.allWhenTouched.doDeleteClone(this) + p.allWhenTouching = p.allWhenTouching.doDeleteClone(this) p.allWhenTouchEnd = p.allWhenTouchEnd.doDeleteClone(this) p.allWhenClick = p.allWhenClick.doDeleteClone(this) p.allWhenMoving = p.allWhenMoving.doDeleteClone(this) @@ -168,10 +168,10 @@ func (p *eventSinkMgr) doWhenTouchStart(this threadObj, obj *Sprite) { }) } -func (p *eventSinkMgr) doWhenTouched(this threadObj, obj *Sprite) { - p.allWhenTouched.asyncCall(false, this, func(ev *eventSink) { +func (p *eventSinkMgr) doWhenTouching(this threadObj, obj *Sprite) { + p.allWhenTouching.asyncCall(false, this, func(ev *eventSink) { if debugEvent { - log.Println("==> onTouched", nameOf(this), obj.name) + log.Println("==> onTouching", nameOf(this), obj.name) } ev.sink.(func(*Sprite))(obj) }) diff --git a/sprite.go b/sprite.go index d5d5843e..aad9da07 100644 --- a/sprite.go +++ b/sprite.go @@ -85,7 +85,7 @@ func (c *Collider) SetTouching(other *Sprite, on bool) { c.others[other] = true c.sprite.fireTouchStart(other) } else { - c.sprite.fireTouched(other) + c.sprite.fireTouching(other) } } else { if exist { @@ -141,7 +141,7 @@ type Sprite struct { hasOnMoving bool hasOnCloned bool hasOnTouchStart bool - hasOnTouched bool + hasOnTouching bool hasOnTouchEnd bool gamer reflect.Value @@ -309,7 +309,7 @@ func (p *Sprite) InitFrom(src *Sprite) { p.hasOnMoving = false p.hasOnCloned = false p.hasOnTouchStart = false - p.hasOnTouched = false + p.hasOnTouching = false p.hasOnTouchEnd = false p.collider.others = make(map[*Sprite]bool) @@ -426,9 +426,9 @@ func (p *Sprite) fireTouchStart(obj *Sprite) { } } -func (p *Sprite) fireTouched(obj *Sprite) { - if p.hasOnTouched { - p.doWhenTouched(p, obj) +func (p *Sprite) fireTouching(obj *Sprite) { + if p.hasOnTouching { + p.doWhenTouching(p, obj) } } From b9c8ca1d001304b7adc05f3e40578ceba1be82de Mon Sep 17 00:00:00 2001 From: qlli Date: Wed, 9 Oct 2024 15:02:40 +0800 Subject: [PATCH 9/9] Tutorial changed from touching to OnTouchStart --- tutorial/05-Animation/SmallEnemy.spx | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/tutorial/05-Animation/SmallEnemy.spx b/tutorial/05-Animation/SmallEnemy.spx index 6ef61727..28b2b39d 100644 --- a/tutorial/05-Animation/SmallEnemy.spx +++ b/tutorial/05-Animation/SmallEnemy.spx @@ -1,3 +1,4 @@ +var life int onStart => { for { wait 0.3 @@ -6,6 +7,7 @@ onStart => { } onCloned => { + life = 3 setXYpos rand(-131, 131), 237 show for { @@ -17,15 +19,11 @@ onCloned => { } } -onCloned => { - life := 3 - for { - wait 0.05 - if touching("Bullet") { - life-- - if life == 0 { - die - } - } - } -} +onTouchStart "Bullet", => { + if life > 0 { + life -- + if life <= 0 { + die + } + } +} \ No newline at end of file