Physics.qml 6.6 KB

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