Gravity.qml 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. import QtQuick 2.5
  2. import Box2D 2.0
  3. import "effects"
  4. Item {
  5. id: root
  6. signal togglePause
  7. signal toggleChaos
  8. signal next
  9. property var pictureDelegate: Qt.createComponent("HorizontalArtDelegate.qml")
  10. property var effectDelegate: Qt.createComponent("VisualEffect.qml")
  11. anchors.fill: parent
  12. QtObject {
  13. id: d
  14. property real pace: settings.pace/60.0
  15. property int itemCount: 0
  16. property int itemTravel: settings.itemTravel
  17. property int primedColumns: 0
  18. property int columnCount: settings.columnCount
  19. property bool running: primedColumns >= columnCount
  20. property bool globalWorld: settings.globalWorld
  21. property string effect: settings.effect
  22. function reset() {
  23. itemCount = 0
  24. primedColumns = 0
  25. }
  26. onColumnCountChanged: reset()
  27. }
  28. World {
  29. id: world
  30. timeStep: d.pace
  31. running: d.globalWorld && d.running
  32. property var limbo: World {
  33. timeStep: world.timeStep
  34. running: world.running
  35. }
  36. }
  37. Component {
  38. id: columnComponent
  39. Item {
  40. id: column
  41. property int stackHeight: 0
  42. property bool full: false
  43. property int xOffset: width * index
  44. onStackHeightChanged: {
  45. if (!column.full && (stackHeight > root.height)) {
  46. d.primedColumns += 1
  47. column.full = true
  48. }
  49. }
  50. function considerImage() {
  51. if (stackHeight < (1.3 + 1/d.columnCount)*root.height) {
  52. addImage()
  53. }
  54. }
  55. function addImage() {
  56. var image = pictureDelegate.createObject(column, { x: -1000, y: -1000 })
  57. if (d.effect !== "" && Effects.validate(d.effect)) {
  58. image.effect = effectDelegate.createObject(column, { target: image, effect: d.effect })
  59. }
  60. image.beyondThePale.connect(removeImage)
  61. image.world = d.globalWorld ? world : isolatedWorld
  62. image.x = xOffset
  63. stackHeight += (image.height + d.itemTravel)
  64. image.y = floor.y - stackHeight
  65. pictureArray.push(image)
  66. d.itemCount++
  67. }
  68. function removeImage(image) {
  69. if (image.effect) {
  70. image.effect.destroy()
  71. }
  72. stackHeight -= (image.height + d.itemTravel)
  73. image.destroy()
  74. d.itemCount--
  75. }
  76. function shiftImageToLimbo() {
  77. if (pictureArray.length > 0) {
  78. var image = pictureArray.shift()
  79. image.world = image.world.limbo
  80. addImage()
  81. }
  82. }
  83. width: parent.width/d.columnCount
  84. anchors { top: parent.top; bottom: parent.bottom }
  85. property var pictureArray: []
  86. property bool fixedRotation: true
  87. World {
  88. id: isolatedWorld
  89. timeStep: d.pace
  90. running: !d.globalWorld && d.running
  91. property var limbo: World {
  92. timeStep: isolatedWorld.timeStep
  93. running: isolatedWorld.running
  94. }
  95. }
  96. RectangleBoxBody {
  97. id: floor
  98. world: isolatedWorld
  99. height: 0
  100. width: parent.width
  101. x: xOffset
  102. anchors {
  103. top: parent.bottom
  104. }
  105. friction: 1
  106. }
  107. Timer {
  108. id: pumpTimer
  109. interval: Math.random()*500 + 500
  110. repeat: true
  111. running: true
  112. onTriggered: considerImage()
  113. }
  114. Timer {
  115. id: deathTimer
  116. running: d.running
  117. repeat: true
  118. interval: 1000*(settings.interval > 60 ? 60*(settings.interval-60) : settings.interval)*(Math.random()+1)
  119. onTriggered: shiftImageToLimbo()
  120. }
  121. Connections {
  122. target: root
  123. onTogglePause: deathTimer.running = !deathTimer.running
  124. onNext: deathTimer.triggered()
  125. onToggleChaos: fixedRotation = !fixedRotation
  126. }
  127. Timer {
  128. id: settleTimer
  129. running: false
  130. interval: 200
  131. onTriggered: deathTimer.triggered()
  132. }
  133. }
  134. }
  135. // floor
  136. RectangleBoxBody {
  137. id: globalFloor
  138. world: world
  139. height: 0
  140. anchors {
  141. left: parent.left
  142. right: parent.right
  143. top: parent.bottom
  144. }
  145. friction: 1
  146. }
  147. DebugDraw {
  148. id: debugDraw
  149. enabled: false
  150. z: 1
  151. world: world
  152. anchors.fill: parent
  153. opacity: 0.75
  154. visible: enabled
  155. }
  156. Repeater {
  157. model: d.columnCount
  158. delegate: columnComponent
  159. }
  160. // TODO: The boot (Monty Python foot) of death to be applied to the stacks
  161. RectangleBoxBody {
  162. id: rect
  163. enabled: false
  164. visible: false
  165. friction: 1.0
  166. density: 1000
  167. color: "red"
  168. width: 50; height: 50
  169. bullet: true
  170. SequentialAnimation {
  171. id: murderAnimation
  172. //loops: Animation.Infinite
  173. //running: true
  174. ScriptAction { script: { root.togglePause() } }
  175. ScriptAction { script: { rect.world = worldArray.pop() } }
  176. PropertyAction { target: rect; property: "x"; value: -rect.width }
  177. PropertyAction { target: rect; property: "y"; value: root.height }
  178. ParallelAnimation {
  179. NumberAnimation { target: rect; property: "x"; to: 2560; duration: 1000 }
  180. NumberAnimation { target: rect; property: "y"; to: 0; duration: 1000 }
  181. }
  182. }
  183. }
  184. Rectangle {
  185. visible: settings.viewItemCount
  186. z: 1
  187. color: "black"
  188. anchors { right: parent.right; top: parent.top }
  189. width: itemCountLabel.width
  190. height: itemCountLabel.height
  191. Text {
  192. id: itemCountLabel
  193. font.pixelSize: 100
  194. text: d.itemCount
  195. color: "white"
  196. }
  197. }
  198. Keys.onUpPressed: root.togglePause()
  199. Keys.onDownPressed: root.toggleChaos() //root.next()
  200. Component.onCompleted: {
  201. pictureDelegate.status !== Component.Ready && console.log('Component failed with:' + pictureDelegate.errorString())
  202. effectDelegate.status !== Component.Ready && console.log('Component failed with:' + effectDelegate.errorString())
  203. }
  204. }