summaryrefslogtreecommitdiff
path: root/nekowatchlet/Neko.qml
diff options
context:
space:
mode:
Diffstat (limited to 'nekowatchlet/Neko.qml')
-rw-r--r--nekowatchlet/Neko.qml176
1 files changed, 176 insertions, 0 deletions
diff --git a/nekowatchlet/Neko.qml b/nekowatchlet/Neko.qml
new file mode 100644
index 0000000..b8b08ad
--- /dev/null
+++ b/nekowatchlet/Neko.qml
@@ -0,0 +1,176 @@
+import QtQuick 1.0
+
+Item {
+ id: neko
+ height: 32
+ width: 32
+ clip: true
+
+ property int targetX;
+ property int targetY;
+ property alias imageSource: sprite.source
+ property bool running: true
+
+ property int maxSpeed: 6
+
+ property int _anim
+ property int _animFrames
+ property int _animCurFrame
+
+ property int _distanceX: targetX - x - (width / 2)
+ property int _distanceY: targetY - y - (5 * height / 6)
+ property int _distance: Math.sqrt(_distanceX * _distanceX + _distanceY * _distanceY)
+
+ property int _calcSpeedX: _distance < maxSpeed ?
+ _distanceX :
+ ((maxSpeed * _distanceX) / _distance)
+ property int _calcSpeedY: _distance < maxSpeed ?
+ _distanceY :
+ ((maxSpeed * _distanceY) / _distance)
+
+ property real _calcAngle: Math.atan2(_calcSpeedY, _calcSpeedX)
+
+ property int _speedX: 0
+ property int _speedY: 0
+
+ signal arrived
+
+ function chooseWalkAnimation(speedX, speedY, angle) {
+ var PiPer8 = Math.PI / 8;
+
+ if (angle > 7 * PiPer8) {
+ return 6; // left
+ } else if (angle > 5 * PiPer8) {
+ return 2; // dwleft
+ } else if (angle > 3 * PiPer8) {
+ return 0; // down
+ } else if (angle > 1 * PiPer8) {
+ return 3; // dwright
+ } else if (angle > -1 * PiPer8) {
+ return 9; // right
+ } else if (angle > -3 * PiPer8) {
+ return 14; // upright
+ } else if (angle > -5 * PiPer8) {
+ return 12; // up
+ } else {
+ return 13; // upleft
+ }
+ }
+
+ Image {
+ id: sprite
+ source: "neko.png"
+
+ x: -(neko.width * neko._animCurFrame)
+ y: -(neko.height * neko._anim)
+ }
+
+ Timer {
+ id: timer
+ interval: 250
+ running: neko.running
+ repeat: true
+ onTriggered: {
+ neko._animCurFrame = (_animCurFrame + 1) % _animFrames
+ neko.x = neko.x + _speedX;
+ neko.y = neko.y + _speedY;
+
+ if (state == "WALKING" && _distance == 0) {
+ neko.arrived();
+ }
+ }
+ }
+
+ Timer {
+ id: idleToScratchTimer
+ onTriggered: neko.state = "SCRATCHING"
+ }
+
+ Timer {
+ id: idleToYawnTimer
+ onTriggered: neko.state = "YAWNING"
+ }
+
+ Timer {
+ id: scrachTimer
+ interval: timer.interval * 2
+ running: neko.running && state === "SCRATCHING"
+ onTriggered: neko.state = "IDLING"
+ }
+
+ Timer {
+ id: yawnTimer
+ interval: timer.interval * 3
+ running: neko.running && state === "YAWNING"
+ onTriggered: neko.state = "IDLING"
+ }
+
+ onTargetXChanged: state = "WALKING"
+ onTargetYChanged: state = "WALKING"
+
+ onArrived: state = "IDLING"
+
+ states: [
+ State {
+ name: "SLEEPING"
+ PropertyChanges {
+ target: neko
+ _anim: 11 // sleep
+ _animFrames: 2
+ _speedX: 0
+ _speedY: 0
+ }
+ },
+ State {
+ name: "IDLING"
+ PropertyChanges {
+ target: neko
+ _anim: 4 // jare
+ _animFrames: 1
+ _animCurFrame: 0
+ _speedX: 0
+ _speedY: 0
+ }
+ PropertyChanges {
+ target: idleToScratchTimer
+ interval: Math.random() * 10000
+ running: neko.running && state == "IDLING"
+ }
+ PropertyChanges {
+ target: idleToYawnTimer
+ interval: Math.random() * 20000
+ running: neko.running && state == "IDLING"
+ }
+ },
+ State {
+ name: "SCRATCHING"
+ PropertyChanges {
+ target: neko
+ _anim: 5 // kaki
+ _animFrames: 2
+ _speedX: 0
+ _speedY: 0
+ }
+ },
+ State {
+ name: "YAWNING"
+ PropertyChanges {
+ target: neko
+ _anim: 8 // mati
+ _animFrames: 2
+ _speedX: 0
+ _speedY: 0
+ }
+ },
+ State {
+ name: "WALKING"
+ PropertyChanges {
+ target: neko
+ _anim: chooseWalkAnimation(_calcSpeedX, _calcSpeedY, _calcAngle)
+ _animFrames: 2
+ _speedX: _calcSpeedX
+ _speedY: _calcSpeedY
+ }
+ }
+ ]
+}