vendredi 24 juin 2016
deleting entity vplay gives nonetype error
I am new to VPlay and QT and I am working through the VPlay tutorials.
I am currently wrapping up the box-stacking game making tutorial up to the point where I create boxes and then need to delete all of the box entities when a box has reached the top.
However, when I get a box reaching the top, then my application crashes.
I took a look through the debugger (and I am not very familiar with it since I am a beginner) but I did see that an object with "No value"/"nonetype"/something along those lines, and I do not know how to fix this/debug this. [I found this problem by dragging a box to the top of the screen, where it hits the top wall, which makes the EntityManager delete every box that there is (or hopefully,so)].
If anyone could please explain to me not just what the error is, but how to detect such errors in the future (since I am a newbie to this debugger- having previously used xcode), that would be great.
My code is as following [please assume that all images, sound effects, and particle effects are in the right directory and are good files. I can post these files here, if you want].
My code is here: (Main.qml)
import VPlay 2.0
import QtQuick 2.0
GameWindow
{
id: gameWindow
//start physics once the splash screen has disappeared, else the box would fall out of the screen
onSplashScreenFinished: physicsWorld.running = true
EntityManager
{
id: entityManager
entityContainer: scene
}
Scene
{
id: scene
//gets increased when a new box is created, and reset to 0 when a new game is started
//start with 1 because initially 1 Box is created
property int createdBoxes: 0
//display the amount of stacked boxes
Text
{
text: "Boxes: " + scene.createdBoxes
color: "white"
z: 1 //put on top of everything else in the Scene
}
Timer
{
id: timer
interval: Math.random()*3000 + 2000
running: true //start running from the beginning, when the scene is loaded
repeat: true //otherwise restart won't work
onTriggered:
{
var newEntityProperties =
{
//safetyZoneHorizontal = box.width*SQRT(2)/2+LeftWall.width -> which is ~ 50
//vary x between [safetyZoneHorizontal ... scene.width-safetyZoneHorizontal]
x: Math.random() * (scene.width-2*50) + 50,
y: 50, //position on top of the scene or at least below the top wall
rotation: Math.random()*360
}
entityManager.createEntityFromUrlWithProperties(Qt.resolvedUrl("Box.qml"), newEntityProperties);
//increase the createdBoxes number
scene.createdBoxes++
//recalculate new interval between 2000 and 5000 ms
interval = Math.random() * 3000 + 2000
//restart the timer
timer.restart()
}
}
Component
{
id: mouseJoint
MouseJoint
{
//make this high enough so the box with its density is moved quickly
maxForce: 1000000
//the damping ratio. 0= no damping, 1= critical damping. default is 0.7
dampingRatio: 1
//the response speed. default is 5
frequencyHz: 2
}
}
//when the user presses a box, move it towards the touch position
MouseArea
{
anchors.fill: parent
property Body selectedBody: null
property MouseJoint mouseJointWhileDragging: null
onPressed:
{
selectedBody = physicsWorld.bodyAt(Qt.point(mouseX,mouseY));
console.debug("selected body at position",mouseX,mouseY,":",selectedBody);
//if the user selected a body, this if-check is true
if (selectedBody)
{
//create a new mouseJoint
mouseJointWhileDragging = mouseJoint.createObject(physicsWorld)
//set the target position to the current touch position (initial position)
mouseJointWhileDragging.target = Qt.point(mouseX,mouseY)
//connect the joint with the body
mouseJointWhileDragging.bodyB = selectedBody
}
}
onPositionChanged:
{
//this check is also necessary because the user might also drag when no initial body was selected
if (mouseJointWhileDragging)
mouseJointWhileDragging.target = Qt.point(mouseX,mouseY)
}
onReleased:
{
//if a user pressed a body initially, remove the created MouseJoint
if (selectedBody)
{
selectedBody = null
if (mouseJointWhileDragging)
mouseJointWhileDragging.destroy()
}
}
}
Rectangle
{
//the game's background
id:background
anchors.fill: scene.gameWindowAnchorItem
color: "black"
}
PhysicsWorld
{
id: physicsWorld
//physics is disabled initially and enabled after the splash is finished
running: false
gravity.y: 9.81
z: 10 //draw the debugDraw on top of the entities
//these are the perfomance settings to avoid boxes colliding too far together
//set them as low as possible so that it still looks good
updatesPerSecondForPhysics: 60
velocityIterations: 5
positionIterations: 5
//set this to true to see the debug draw of the physics system
//this displays all bodies, joints, and forces, which is great for debugging
debugDrawVisible: false
}
Box
{
x: scene.width/2
y: 50
}
Wall
{
height: 20
anchors
{
bottom: scene.bottom
left: scene.left
right: scene.right
}
}
//adding the walls to the screen
Wall
{
//bottom wall
height: 20
anchors
{
bottom: scene.bottom
left: scene.left
right: scene.right
}
}
Wall
{
//left wall
width: 20
height: scene.height
anchors
{
left: scene.left
}
}
Wall
{
//right wall
width: 20
height: scene.height
anchors
{
right: scene.right
}
}
Wall
{
//top wall
height: 20
width: scene.width
anchors
{
top: scene.top
}
color: "red" //make top wall red
onCollidedWithBox:
{
console.debug("DEBUG: in onColliededWithBox");
//gets called when the wall collides with a box and the game should restart
//remove all entities of type "box" but not the walls
entityManager.removeAllEntities();
console.debug("removed all boxes");
//reset the createdBoxes amount
scene.createdBoxes = 0;
console.debug("Set createdBoxes to 0 and left function");
}
}
}}
and then Box.qml:
import QtQuick 2.0
import VPlay 2.0
EntityBase
{
id: box
entityType: "box"
//the origin (the 0/0 position of the entity) of this entity is in the center
//thus we cannot use an anchors.fill: parent in Image and BoxCollider,
//otherwise it would use the top left corner as the origin
width: 32
height: 32
//the 0/0 of the entity should be the center of the collider and image
//this is required when a width & height are set to the entity!
//in that case, the rotation should be applied around the center (which is top-left,
//not the width/2, height/2 Item.center, which is the default value
transformOrigin: Item.TopLeft
Image
{
id: boxImage
source: "../assets/box.png"
//set the size of the image to one of the box collider and not vice versa because
//the physics properties depend on the collider size
anchors.fill: boxCollider
}
BoxCollider
{
id: boxCollider
//the size affects the physics settings (the bigger the heaver)
//this is set automatically in any collider- the default size is the one of the parent!
//width: parent.width
//height: parent.height
//the collider should have its origin at the x/y of the entity (so the center is in the TopLeft)
x: -width/2
y: -height/2
friction: 1.6
restitution: 0 //restitution is bounciness- a wooden box does not bounce
density: 0.1 //makes the box more heavy
fixture.onBeginContact:
{
//when colliding with another entity, play the sound and start particle effect
collisionSound.play();
collisionParticleEffect.start();
}
}
//the soundEffect is played at a collision
SoundEffectVPlay
{
id: collisionSound
source: "../assets/boxCollision.wav"
}
//the Particle effect is started at a collision
ParticleVPlay
{
id: collisionParticleEffect
fileName: "../assets/SmokeParticleCpy.json"
}
}
and then Wall.qml:
import QtQuick 2.0
import VPlay 2.0
//for accessing the Body.static type
EntityBase
{
entityType: "wall"
//this gets used by the top wall to detect when the game is over
signal collidedWithBox
//this allows setting the color property or the Rectangle from outside,
//to use another color for the top wall
property alias color: rectangle.color
property alias collider: collider
preventFromRemovalFromEntityManager: true
Rectangle
{
id: rectangle
color: "blue"
anchors.fill: parent
}
BoxCollider
{
id: collider
anchors.fill: parent
bodyType: Body.Static //the body should not move
fixture.onBeginContact: collidedWithBox()
}}
and then the Main.cpp file that runs all of this stuff is:
#include <QApplication>
#include <VPApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
VPApplication vplay;
// QQmlApplicationEngine is the preferred way to start qml projects since Qt 5.2
// if you have older projects using Qt App wizards from previous QtCreator versions than 3.1, please change them to QQmlApplicationEngine
QQmlApplicationEngine engine;
vplay.initialize(&engine);
// use this during development
// for PUBLISHING, use the entry point below
vplay.setMainQmlFileName(QStringLiteral("qml/Main.qml"));
// use this instead of the above call to avoid deployment of the qml files and compile them into the binary with qt's resource system qrc
// this is the preferred deployment option for publishing games to the app stores, because then your qml files and js files are protected
// to avoid deployment of your qml files and images, also comment the DEPLOYMENTFOLDERS command in the .pro file
// also see the .pro file for more details
// vplay.setMainQmlFileName(QStringLiteral("qrc:/qml/Main.qml"));
engine.load(QUrl(vplay.mainQmlFileName()));
return app.exec();
}
And the error thread is:
eERROR: Lldb stderr: Exception in thread Thread-1:
eTraceback (most recent call last):
e File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 810, in __bootstrap_inner
e self.run()
e File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 763, in run
e self.__target(*self.__args, **self.__kwargs)
e File "/Users/Nata/vplay/Qt Creator.app/Contents/Resources/debugger/lldbbridge.py", line 769, in loop
e self.handleEvent(event)
e File "/Users/Nata/vplay/Qt Creator.app/Contents/Resources/debugger/lldbbridge.py", line 1409, in handleEvent
e % self.hexencode(msg))
e File "/Users/Nata/vplay/Qt Creator.app/Contents/Resources/debugger/dumper.py", line 479, in hexencode
e return s.encode("hex")
eAttributeError: 'NoneType' object has no attribute 'encode'
Inscription à :
Publier les commentaires (Atom)
Aucun commentaire:
Enregistrer un commentaire