[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