Hi,
I wrote a demo project upon a developer request in the forums a while ago, which matches your requirements pretty much. I changed the code a bit for you now, hopefully this gives you an idea of how to achieve it. It was about a gravitational pull towards the player, the major difference now is the applyGravityImpulse
() function of the object, which now applies a constant velocity instead of an impulse (i didn’t change the old names of functions etc). So here’s the code:
Player.qml
import VPlay 1.0
import QtQuick 1.1
EntityBase {
id: player
entityType: "player"
width: 25
height: 25
signal collidedWithObject(variant object)
Rectangle {
width: player.width
height: player.height
x: -player.width/2
y: -player.height/2
color: "blue"
}
BoxCollider {
id: collider
width: player.width
height: player.height
x: -player.width/2
y: -player.height/2
bodyType: Body.Static
fixture.onBeginContact: {
var collidedColliderComponent = other.parent.parent;
var collidedEntity = collidedColliderComponent.parent;
var collidedEntityType = collidedEntity.entityType;
if(collidedEntityType === "object")
collidedWithObject(collidedEntity)
}
}
function getPosition() {
return collider.body.getWorldCenter()
}
}
Object.qml
import VPlay 1.0
import QtQuick 1.1
EntityBase {
id: object
entityType: "object"
width: 10
height: 10
Rectangle {
width: object.width
height: object.height
x: -object.width/2
y: -object.height/2
color: "red"
}
BoxCollider {
id: collider
width: object.width
height: object.height
x: -object.width/2
y: -object.height/2
}
function getPosition() {
return collider.body.getWorldCenter()
}
function applyGravityImpulse(forward) {
collider.linearVelocity.x = forward.x
collider.linearVelocity.y = forward.y
}
}
GravityLogic.js
var player
var objects = new Array
var speed
function addObject(entityId) {
objects.push(entityManager.getEntityById(entityId))
}
function removeObject(entityId) {
for(var i=0; i<objects.length; i++) {
if(objects[i].entityId === entityId) {
objects.splice(i,1)
return
}
}
}
function applyGravity() {
for(var i = 0; i < objects.length; i++) {
var object = objects[i]
var objectPosition = object.getPosition()
var playerPosition = player.getPosition()
// the distance could be useful if you want to apply the gravity only within a radius around the player
var distance = Math.sqrt(Math.pow(Math.abs(objectPosition.x-playerPosition.x),2)+Math.pow(Math.abs(objectPosition.y-playerPosition.y),2))
var atanY = playerPosition.y - objectPosition.y;
var atanX = playerPosition.x - objectPosition.x;
var angle = Math.atan2(atanY, atanX);
var impulseX = speed*Math.cos(angle)
var impulseY = speed*Math.sin(angle)
object.applyGravityImpulse(Qt.point(impulseX,impulseY))
}
}
main.qml
import VPlay 1.0
import QtQuick 1.1
import "GravityLogic.js" as Gravity
GameWindow {
EntityManager {
id: entityManager
entityContainer: scene
}
Scene {
id: scene
property alias player: player
PhysicsWorld {
id: world
}
Player {
id: player
x: scene.width/2
y: scene.height/2
onCollidedWithObject: {
Gravity.removeObject(object.entityId)
object.removeEntity()
}
}
Timer {
id: gravityTimer
interval: 300
repeat: true
running: false
onTriggered: {
Gravity.applyGravity()
}
}
Component.onCompleted: {
Gravity.player = player
Gravity.speed = 20
for(var i = 0; i <50; i++) {
var entityId = entityManager.createEntityFromUrlWithProperties(Qt.resolvedUrl("Object.qml"),{"x":Math.random()*scene.width, "y":Math.random()*scene.height})
Gravity.addObject(entityId)
}
gravityTimer.start()
}
}
}
If you have any questions about the code, feel free to ask 🙂
Cheers,
Alex