[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    KDE/kdegames/kolf
From:       Stefan Majewsky <majewsky () gmx ! net>
Date:       2010-10-31 23:23:19
Message-ID: 20101031232319.CF028AC8A6 () svn ! kde ! org
[Download RAW message or body]

SVN commit 1191712 by majewsky:

Add methods to CanvasItem to synchronize visual and physical representation.

Box2D's bodies maintain their own coordinate systems and velocities,
which we have to keep in sync with the CanvasItems. I've added a new
physicalVelocity property to CanvasItem which is temporarily separate
from the current velocity, because both the home-grown and Box2D-based
time evolution will run in parallel for some time, until everything has
been ported to Box2D.

Setting CanvasItem::velocity() will result in the object participating
in the home-grown time evolution, while a non-zero physicalVelocity()
will be applied by Box2D. Hence, while the ball does not yet have a
physicalVelocity(), Box2D will not resolve its collisions.

 M  +38 -0     canvasitem.cpp  
 M  +21 -0     canvasitem.h  
 M  +16 -0     game.h  
 M  +2 -0      slope.h  


--- trunk/KDE/kdegames/kolf/canvasitem.cpp #1191711:1191712
@@ -30,6 +30,7 @@
 	, m_body(0)
 	, m_overlay(0)
 	, m_simulationType(CanvasItem::CollisionSimulation)
+	, m_velocityChanged(true)
 {
 	b2BodyDef bodyDef;
 	bodyDef.userData = this;
@@ -130,6 +131,43 @@
 	}
 }
 
+QPointF CanvasItem::physicalVelocity() const
+{
+	return m_physicalVelocity;
+}
+
+void CanvasItem::setPhysicalVelocity(const QPointF& physicalVelocity)
+{
+	if (m_physicalVelocity != physicalVelocity)
+	{
+		m_physicalVelocity = physicalVelocity;
+		m_velocityChanged = true;
+	}
+}
+
+void CanvasItem::startSimulation()
+{
+	const QPointF position = getPosition();
+	m_body->SetTransform(b2Vec2(position.x(), position.y()), 0);
+	if (m_velocityChanged)
+		m_body->SetLinearVelocity(b2Vec2(m_physicalVelocity.x(), m_physicalVelocity.y()));
+	m_velocityChanged = false;
+}
+
+void CanvasItem::endSimulation()
+{
+	//read position
+	b2Vec2 v = m_body->GetPosition();
+	setPosition(QPointF(v.x, v.y));
+	//read velocity
+	v = m_body->GetLinearVelocity();
+	const QPointF velocity(v.x, v.y);
+	setVelocity(velocity);
+	//unset m_velocityChanged if there was no manual change since last simulation step \
(TODO: necessary?) +	if (velocity == m_physicalVelocity)
+		m_velocityChanged = false;
+}
+
 Kolf::Overlay* CanvasItem::overlay(bool createIfNecessary)
 {
 	//the overlay is created once it is requested
--- trunk/KDE/kdegames/kolf/canvasitem.h #1191711:1191712
@@ -117,6 +117,10 @@
 	virtual void setVelocity(const Vector& velocity) { m_velocity = velocity; }
 	Vector velocity() const { return m_velocity; }
 	virtual void moveBy(double , double) { kDebug(12007) << "Warning, empty moveBy \
used";} //needed so that float can call the own custom moveBy()s of everything on it \
+ +	//The following is needed temporarily while CanvasItem is not a QGraphicsItem by \
itself. +	virtual void setPosition(const QPointF& pos) = 0;
+	virtual QPointF getPosition() const = 0;
 protected:
 	///pointer to main KolfGame
 	KolfGame *game;
@@ -151,10 +155,21 @@
 
 		QList<Kolf::Shape*> shapes() const { return m_shapes; }
 		Kolf::Overlay* overlay(bool createIfNecessary = true);
+
+		///This is the velocity used by the physics engine: In each time step,
+		///the position of this canvas item changes by the value of this property.
+		QPointF physicalVelocity() const;
+		void setPhysicalVelocity(const QPointF& physicalVelocity);
 	protected:
 		void addShape(Kolf::Shape* shape);
 		///Configure how this object will participate in physical simulation.
 		void setSimulationType(CanvasItem::SimulationType type);
+
+		///The physics engine calls this method to prepare the object for the following \
simulation step. Subclass implementations have to call the base implementation just \
before returning. +		virtual void startSimulation();
+		///The physics engine calls this method after calculating the next frame, to let \
the objects update their representation. Subclass implementations have to call the \
base implementation before anything else. +		virtual void endSimulation();
+
 		///Creates the optimal overlay for this object. The implementation does not have \
to propagate its properties to the overlay, as the overlay is updated just after it \
has been created.  ///@warning Do not actually call this function from subclass \
implementations. Use overlay() instead.  virtual Kolf::Overlay* createOverlay() { \
return 0; } //TODO: make this pure virtual when all CanvasItems are QGraphicsItems \
and implement createOverlay() (and then disallow createOverlay() == 0) @@ -167,6 \
+182,9 @@  Kolf::Overlay* m_overlay;
 		QList<Kolf::Shape*> m_shapes;
 		CanvasItem::SimulationType m_simulationType;
+		QPointF m_physicalVelocity;
+		bool m_velocityChanged; //tells whether velocity has been changed programmatically \
after last simulation step +		//The rationale behind this variable is that Box2D \
sometimes has very low velocities (~1e-10) during contacts. The QPointF conversion \
could create rounding errors on some platforms.  };
 
 //WARNING: pos() is at center (not at top-left edge of bounding rect!)
@@ -189,6 +207,9 @@
 
 		void saveSize(KConfigGroup* group);
 		void loadSize(KConfigGroup* group);
+
+		virtual void setPosition(const QPointF& pos) { QGraphicsItem::setPos(pos); }
+		virtual QPointF getPosition() const { return QGraphicsItem::pos(); }
 	private:
 		QGraphicsEllipseItem* m_ellipseItem;
 };
--- trunk/KDE/kdegames/kolf/game.h #1191711:1191712
@@ -170,6 +170,8 @@
 	void setSizeFactor(double newFactor) { m_sizeFactor = newFactor; }
 	virtual void setSize(const QSizeF& size);
 
+	virtual void setPosition(const QPointF& pos) { QGraphicsItem::setPos(pos); }
+	virtual QPointF getPosition() const { return QGraphicsItem::pos(); }
 protected:
 	Tagaro::SpriteObjectItem *rect;
 	double m_sizeFactor;
@@ -312,6 +314,9 @@
 	void setArrowPen(QPen pen) { arrow->setPen(pen); }
 	virtual Config *config(QWidget *parent);
 	BlackHole *blackHole;
+
+	virtual void setPosition(const QPointF& pos) { QGraphicsItem::setPos(pos); }
+	virtual QPointF getPosition() const { return QGraphicsItem::pos(); }
 protected:
 	Arrow *arrow;
 };
@@ -422,6 +427,8 @@
 
 	void setLine(const QLineF& line);
 
+	virtual void setPosition(const QPointF& pos) { QGraphicsItem::setPos(pos); }
+	virtual QPointF getPosition() const { return QGraphicsItem::pos(); }
 protected:
 	WallPoint *startItem;
 	WallPoint *endItem;
@@ -454,6 +461,9 @@
 	double height() { return rect().height(); }
 
 	Wall *parentWall() { return wall; }
+
+	virtual void setPosition(const QPointF& pos) { QGraphicsItem::setPos(pos); }
+	virtual QPointF getPosition() const { return QGraphicsItem::pos(); }
 protected:
 	Wall *wall;
 	bool editing;
@@ -491,6 +501,8 @@
 	virtual void moveBy(double dx, double dy);
 	void setShowGuideLine(bool yes);
 
+	virtual void setPosition(const QPointF& pos) { QGraphicsItem::setPos(pos); }
+	virtual QPointF getPosition() const { return QGraphicsItem::pos(); }
 private:
 	QPointF midPoint;
 	double maxAngle;
@@ -566,6 +578,8 @@
 	double width() {return Tagaro::SpriteObjectItem::size().width(); }
 	double height() {return Tagaro::SpriteObjectItem::size().height(); }
 
+	virtual void setPosition(const QPointF& pos) { QGraphicsItem::setPos(pos); }
+	virtual QPointF getPosition() const { return QGraphicsItem::pos(); }
 protected:
 	Wall *topWall;
 	Wall *botWall;
@@ -702,6 +716,8 @@
 	void borderWallsChanged(bool yes);
 	bool borderWalls() const { return m_borderWalls; }
 
+	virtual void setPosition(const QPointF& pos) { Q_UNUSED(pos) }
+	virtual QPointF getPosition() const { return QPointF(); }
 private:
 	QString m_author;
 	QString m_name;
--- trunk/KDE/kdegames/kolf/slope.h #1191711:1191712
@@ -88,6 +88,8 @@
 	double width() const { return size().width(); }
 	double height() const { return size().height(); }
 
+	virtual void setPosition(const QPointF& pos) { QGraphicsItem::setPos(pos); }
+	virtual QPointF getPosition() const { return QGraphicsItem::pos(); }
 private:
 	GradientType type;
 	inline void setType(GradientType type);


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic