Example #1
0
Vec2 Box2::getCenter() const
{
	Vec2 center;
	center.add(min,max);
	center *= NxReal(0.5);

	return center;
}
Example #2
0
void HRocker::onTouchMoved(Touch* touch, Event* event) {
	Vec2 touchPoint = touch->getLocationInView();
	touchPoint = Director::getInstance()->convertToGL(touchPoint);
	if (touchPoint.distance(centerPoint) > radius) {
		touchPoint.subtract(centerPoint);
		touchPoint.normalize();
		touchPoint *= radius;
		touchPoint.add(centerPoint);
		currentPoint = touchPoint;
//		currentPoint = ccpAdd(centerPoint,
//				ccpMult(ccpNormalize(ccpSub(touchPoint, centerPoint)), radius));
	} else {
		currentPoint = touchPoint;
	}
}
Example #3
0
void Joint::update(float delta)
{

	Vec2 pa = pA;
	Vec2 pb = pB;

	RotMat mA(A->angle);
	RotMat mB(B->angle);

	pa.rotate(mA);
	pb.rotate(mB);

	pa.add(A->position);
	pb.add(B->position);


	Vec2 ra = pa - A->position;
	Vec2 rpa = Vec2(-ra.y, ra.x);

	Vec2 rb = pb - B->position;
	Vec2 rpb(-rb.y, rb.x);


	float d = distance - (pa-pb).value();

	Vec2 n = pa-pb;

	if (n.value() == 0.0f)
		return;

	n.normalize();

	//position correction
	float s = d / (A->inv_mass + B->inv_mass );

	if(A->dynamic == true )
	A->translate(n * s * A->inv_mass );
	

	if(B->dynamic == true )
	B->translate( n * s * B->inv_mass * -1);

	//relative velocities
	Vec2 v1 = A->velocity + rpa*A->omega;
	Vec2 v2 = B->velocity + rpb*B->omega;

	Vec2 v = v1-v2;

	//calculate impulse
	float j = -Scalar(v, n) / (A->inv_mass  + B->inv_mass  + Scalar(rpa, n)*Scalar(rpa, n)*A->inv_inertia  + Scalar(rpb, n)*Scalar(rpb, n)*B->inv_inertia );

	

	//apply impulse
	if(A->dynamic == true )
	{
	A->velocity.add( n * A->inv_mass * j );
	A->omega += Scalar(rpa, n*j) * A->inv_inertia ;
	}

	if(B->dynamic == true )
	{
	B->velocity.add (n * B->inv_mass * j * -1 );
	B->omega -= Scalar(rpb, n*j) * B->inv_inertia ;
	}
	/*
  Vec2 AB = Vector(A->position , B->position );             // Wektor AB

  float translation = AB.value() - distance;                // wymagana translacja cia³

  AB.normalize();                                           // normalizuje wektor

  Vec2 RelVel = B->velocity - A->velocity  ;                // Wypadkowa prêdkoœæ cia³

  float vel = Scalar(RelVel , AB) + translation;
        
 vel = vel / ( A->inv_mass + B->inv_mass );

 AB = AB * vel;
 
 A->ApplyImpulse(AB);
 B->ApplyImpulse(AB * -1);
 */
}
void SimplePhysicObject::updateForStatic(float dt, const std::vector<SimplePhysicObject*>& staticObjs)
{
	if (this->type == SPOT::SPOT_DYNAMIC){
		//if (isOnPlatform) return;
		//--- flag to check what kind if collision has occurred
		bool collideX = true, collideBottom = true, collideTop = true;

		for (int iteration = 0; iteration < 3 && (collideX || collideTop || collideBottom); iteration++){
			//------------ for each iterating
			std::set<int> boundObjects;
			//--- get next position
			Vec2 nextPosition = this->getPosition();
			nextPosition.add(verlocity);
			//--- create next position bounding box
			Rect nextPositionRect = Rect(
				std::min(this->getPosition().x, nextPosition.x),
				std::min(this->getPosition().y, nextPosition.y),
				size.width,
				size.height
				);
			//--- check each object to see whether it intersects with this object's bounding box
			for (int i = 0; i < staticObjs.size(); i++)
			{
				//--- create bounding box for this static object
				Rect staticObjRect = Rect(staticObjs[i]->getPosition().x, staticObjs[i]->getPosition().y, staticObjs[i]->getSize().width, staticObjs[i]->getSize().height);
				//--- create bounding box that used to check collide
				Rect bounds = Rect(nextPositionRect);
				bounds.merge(staticObjRect);
				//--- If a bnounding box intersects with this object's bounding box, add the geometry to to list to check for collisions
				if (bounds.getMaxX() - bounds.getMinX() < staticObjRect.getMaxX() - staticObjRect.getMinX() + nextPositionRect.getMaxX() - nextPositionRect.getMinX() &&
					bounds.getMaxY() - bounds.getMinY() < staticObjRect.getMaxY() - staticObjRect.getMinY() + nextPositionRect.getMaxY() - nextPositionRect.getMinY())
				{
					//-- add this index to bound objects to check collision
					boundObjects.insert(i);
				}
			}

			//-- No collisions found yet
			collideX = collideTop = collideBottom = false;
			//---------------------------------------------------
			float projectedMoveX, projectedMoveY, originalMoveX, originalMoveY, nextMoveX, nextMoveY;
			float vectorLength;
			int segments;
			//--- store original move 
			originalMoveX = nextPosition.x - this->getPosition().x;
			originalMoveY = nextPosition.y - this->getPosition().y;
			nextMoveX = originalMoveX;
			nextMoveY = originalMoveY;
			//-- iterate over each object whose boudning box intersects with this object's bounding box
			//-- until a collision is found
			for (auto it = boundObjects.begin(); it != boundObjects.end() && !collideX && !collideTop && !collideBottom; ++it)
			{
				//----------------------------------------------------
				// Speculative contacts section
				//----------------------------------------------------
				//-- get this static rect
				Rect staticObjRect = Rect(staticObjs[*it]->getPosition().x, staticObjs[*it]->getPosition().y, staticObjs[*it]->getSize().width, staticObjs[*it]->getSize().height);
				Rect specIntersection;
				specIntersection = CCRectMake(std::max(nextPositionRect.getMinX(), staticObjRect.getMinX()), std::max(nextPositionRect.getMinY(), staticObjRect.getMinY()), 0, 0);
				specIntersection.size.width = std::min(nextPositionRect.getMaxX(), staticObjRect.getMaxX()) - specIntersection.getMinX();
				specIntersection.size.height = std::min(nextPositionRect.getMaxY(), staticObjRect.getMaxY()) - specIntersection.getMinY();
				if (specIntersection.getMaxY() - specIntersection.getMinY() >= 1 && specIntersection.getMaxX() - specIntersection.getMinX() >= 1)
				{
					//-- Test four possible directions 
					//-- dir: 0 = top, 1 = bottom, 2 = left, 3 = right
					for (int dir = 0; dir < 4; dir++)
					{
						// skip test if the expected direction of movement make the test irrelevent
						//-----------------------------------------------------------------------
						if (dir == 0 && originalMoveY < 0) continue;
						if (dir == 1 && originalMoveY > 0) continue;
						if (dir == 2 && originalMoveX > 0) continue;
						if (dir == 3 && originalMoveX < 0) continue;

						float safeMoveX = std::max(std::max(specIntersection.getMinX() - (this->getPosition().x + size.width), this->getPosition().x - specIntersection.getMaxX()), 0.0f);
						float safeMoveY = std::max(std::max(specIntersection.getMinY() - (this->getPosition().y + size.height), this->getPosition().y - specIntersection.getMaxY()), 0.0f);
						float safeVecLen = std::sqrt(safeMoveX * safeMoveX + safeMoveY * safeMoveY);
						//-- calculate the lehgth of the movement vector using pythagoras
						vectorLength = std::sqrt(originalMoveX * originalMoveX + originalMoveY* originalMoveY);
						//-- our current position along the anticipated movement vector of this object in this frame
						projectedMoveX = originalMoveX * (safeMoveX / vectorLength);
						projectedMoveY = originalMoveY * (safeMoveY / vectorLength);
						//-- update vector lenght
						vectorLength -= safeVecLen;
						segments = 0;
						//-- we advence along the vector until it intersect with some box
						while (!staticObjRect.containsPoint(Vec2(
							static_cast<int>(objectCollisionPoints[dir * 2].x + this->getPosition().x + projectedMoveX),
							static_cast<int>(objectCollisionPoints[dir * 2].y + this->getPosition().y + projectedMoveY)))
							&&
							!staticObjRect.containsPoint(Vec2(
							static_cast<int>(objectCollisionPoints[dir * 2 + 1].x + this->getPosition().x + projectedMoveX),
							static_cast<int>(objectCollisionPoints[dir * 2 + 1].y + this->getPosition().y + projectedMoveY)))
							&&
							segments < vectorLength)
						{
							projectedMoveX += originalMoveX / vectorLength;
							projectedMoveY += originalMoveY / vectorLength;
							segments++;
						}
						//--- if an intersection occurred
						if (segments < vectorLength){
							//--- apply correction for over-movemnt
							if (segments > 0){
								projectedMoveX -= originalMoveX / vectorLength;
								projectedMoveY -= originalMoveY / vectorLength;
							}
							//--- adjust the X or Y component of the vector depending on
							//--- which direction we are currently testing
							if (dir >= 2 && dir <= 3) nextMoveX = projectedMoveX;
							if (dir >= 0 && dir <= 1) nextMoveY = projectedMoveY;
						}

					}
				}

				//----------------------------------------------------
				// Penetration resolution
				//----------------------------------------------------
				Rect objectNextBound = Rect(
					static_cast<int>(this->getPosition().x + nextMoveX),
					static_cast<int>(this->getPosition().y + nextMoveY),
					size.width,
					size.height
					);
				//--- get intersection of new bounding box to static box
				Rect intersection;
				intersection = CCRectMake(std::max(objectNextBound.getMinX(), staticObjRect.getMinX()), std::max(objectNextBound.getMinY(), staticObjRect.getMinY()), 0, 0);
				intersection.size.width = std::min(objectNextBound.getMaxX(), staticObjRect.getMaxX()) - intersection.getMinX();
				intersection.size.height = std::min(objectNextBound.getMaxY(), staticObjRect.getMaxY()) - intersection.getMinY();
				//--- convert to int to prevent juddering due to floating point dounding errors
				int intX = static_cast<int>(intersection.getMaxX() - intersection.getMinX());
				int intY = static_cast<int>(intersection.getMaxY() - intersection.getMinY());
				for (int dir = 0; dir < 4; dir++)
				{
					if (intersection.containsPoint(Vec2(
						static_cast<int>(objectCollisionPoints[dir * 2].x + this->getPosition().x + nextMoveX),
						static_cast<int>(objectCollisionPoints[dir * 2].y + this->getPosition().y + nextMoveY)))
						||
						intersection.containsPoint(Vec2(
						static_cast<int>(objectCollisionPoints[dir * 2 + 1].x + this->getPosition().x + nextMoveX),
						static_cast<int>(objectCollisionPoints[dir * 2 + 1].y + this->getPosition().y + nextMoveY)))
						)
					{
						switch (dir)
						{
						case 0: nextMoveY -= intY; break;
						case 1: nextMoveY += intY; break;
						case 2: nextMoveX += intX; break;
						case 3: nextMoveX -= intX; break;
						}
					}
				}

				//--- Detect what type of contact has occurred based on a comparison of the original
				if (nextMoveY > originalMoveY && originalMoveY < 0) collideBottom = true;
				if (nextMoveY < originalMoveY && originalMoveY > 0) collideTop = true;
				if (std::abs(nextMoveX - originalMoveX) > 0.01f) collideX = true;

				//--- in this case object cant jump because hit side of something
				//--- must fall down instead
				//--- without this object will still continue trying to travel upwards ( for jump thought behaviour )
				if (collideX && collideTop && verlocity.y > 0)
				{
					verlocity.y = 0;
				}
			}

			//-- if a contact has been deteced, apply the recalculate movement vector
			if (collideBottom || collideTop){
				this->setPositionY(this->getPosition().y + nextMoveY);
				verlocity.y = 0;

				if (collideBottom){
					//TODO: set jumping = false here to reset jump
					if (isJump)
					{
						isJump = false;
						verlocity.x = 0;
					}
				}
			}
			if (collideX){
				this->setPositionX(this->getPosition().x + nextMoveX);
				verlocity.x = 0;
			}

		}
		//--------------------------------------------------------------------------
		// update object position by verlocity
		//--------------------------------------------------------------------------
		this->setPositionX(verlocity.x + this->getPosition().x);
		this->setPositionY(verlocity.y + this->getPosition().y);

		//////////////////////////////////////////////////////////////////////////////
		//--- apply gravity
		///////////////////////////////////////////////////////////////////////////////
		if (!isOnPlatform)
		{
			verlocity.y -= 0.5f;
		}
		



	}// END IF check object is dynamic object
}
Example #5
0
		Vec2 operator+(Vec2 left, const Vec2& right)
		{
			return left.add(right);
		}
Example #6
0
	void ExecFrame::execute_ops(int num)
	{
		int opcode, param;
		floatval fa,fb;
		int ia, ib, ifor, iparam, ijmp;
		//char opfor,pfor;
		Vec2 *v1,*v2;
		Vec2 v;
		VMInterface* obj;
		ExecFrame* frame;
		CodeObj* cobj;
		
		while(num-- != 0)
		{
			opcode = (int)code->code[iptr++];
			param = (int)code->code[iptr++];
			
			//std::cout << opcode << ':' << param << std::endl;
			
			switch(opcode) {
				case OPC_EXIT:
					iptr-=2;
					return;
				case OPC_VMCALL:
					cobj = (CodeObj*)popp();
					ia = popi();
					frame = new ExecFrame(cobj);
					frame->restart();
					if (param > 0) move(param, frame);
					frame->execute();
					if (ia > 0) frame->move(ia, this);
					delete frame;
					break;
			    case OPC_CONSTF:
			    	pushf(code->conarray_f[param]);
			        break;
			    case OPC_CONSTI:
			        pushi(code->conarray_i[param]);
			        break;
			    case OPC_CONSTV:
			    	pushv(code->conarray_v[param]);
			        break;
			    case OPC_CONSTP:
			    	pushp(code->conarray_p[param]);
			    	break;
			    case OPC_PUSHVARF:
			        pushf(vararray_f[param]);
			        break;
			    case OPC_PUSHVARI:
			        pushi(vararray_i[param]);
			        break;
			    case OPC_PUSHVARV:
			        pushv(vararray_v[param]);
			        break;
			    case OPC_PUSHVARP:
			        pushp(vararray_p[param]);
			        break;
				case OPC_POP:
					top -= param;
					break;
			    case OPC_SETVARF:
			        vararray_f[param] = popf();
			        break;
			    case OPC_SETVARI:
			        vararray_i[param] = popi();
			        break;
			    case OPC_SETVARV:
			    	fb = popf();
			    	fa = popf();
			        vararray_v[param].set(fa,fb);
			        break;
			    case OPC_SETVARP:
			        vararray_p[param] = popp();
			        break;
			    case OPC_GETPROP:
			        obj = (VMInterface*)popp();
			        obj->VM_GetProp(this, param);
			        break;
			    case OPC_SETPROP:
			        obj = (VMInterface*)popp();
			        obj->VM_SetProp(this, param);
			        break;
			    case OPC_METCALL:
			        obj = (VMInterface*)popp();
			        obj->VM_MetCall(this, param);
			        break;
			    case OPC_GETPROPV:
			        v1 = (Vec2*)popp();
			        v1->VM_GetProp(this, param);
			        break;
			    case OPC_SETPROPV:		    
			        v1 = (Vec2*)popp();
			        v1->VM_SetProp(this, param);
			        break;
			    case OPC_METCALLV:
			        v1 = (Vec2*)popp();
			        v1->VM_MetCall(this, param);
			        break;
			    case OPC_JUMP:
			        iptr += param*2;
			        break;
			    case OPC_IFJUMP:
			        ia = popi();
			        if (ia == 0) iptr += param*2;
			        break;
			    case OPC_INITFOR:
			        ib = popi();
			        ia = popi();
			        ++iptr;
			        iparam = code->code[iptr++];
			        ijmp = iptr;
			        for(ifor=ia;ifor<ib;++ifor)
			        {
			        	iptr = ijmp;
			        	vararray_i[param] = ifor;
			        	execute_ops(iparam);
			        	/*for(iptr=ijmp;iptr<ijmp+iparam*2;++iptr)
			        	{
					        opfor = code->code[iptr];
					        pfor = code->code[++iptr];
					        if (opfor == OPC_EXIT)
					        {
					        	--iptr;
					        	return;
					        }
			        		execute_op(opfor, pfor);
			        	}*/
			        	 
			        }
			        break;
			    case OPC_LOOP:
			        ; // TODO
			        break;
			    case OPC_I2F:
			    //  this will break is floatval uses doubles !!
			    /*    ia = *((int*)top);
			        *((floatval*)top) = (float)ia;*/
			        ia = popi();
			        pushf((floatval)ia);		        
			        break;
			    case OPC_F2I:
			        /*fa = *((floatval*)top);
			        *((int*)top) = (int)fa;*/
			        fa = popf();
			        pushi((int)fa);		        
			        break;
			    case OPC_VEC2P:
			    	fb = popf();
			    	fa = popf();
			    	v1 = vectemp + (vecidx % 5);
			    	++vecidx;
			    	v1->set(fa,fb);
			    	pushp(v1);
			    	break;
			    case OPC_P2VEC:
			    	v1 = popv();
			    	pushv(*v1);
			    	break;
			    case OPC_LASTVEC:
			    	v1 = vectemp + ((vecidx-1)%5);
			    	pushv(*v1);
			    	break;
			        
		// --------------------------------------------------
		// -------------------- OPERATORS -------------------
		// --------------------------------------------------		        
			        
			    case OPC_OP_ADDFF:
			    	fa = popf();
			        *(((floatval*)top)-1) += fa;
			        break;
			    case OPC_OP_ADDII:
			    	ia = popi();
			        *(((int*)top)-1) += ia;
			        break;
			    case OPC_OP_ADDVV:
			        v2 = popv();
			        v1 = popv();
			        v.set(*v1);
			        v.add(*v2);
			        pushv(v);
			        break;
			    case OPC_OP_ANDBB:
			        ib = popi();
			        ia = popi();
			        pushi(ia & ib);
			        break;
			    case OPC_OP_DIVFF:
			    	fa = popf();
			        *(((floatval*)top)-1) /= fa;
			        break;
			    case OPC_OP_DIVII:
			    	ia = popi();
			        *(((int*)top)-1) /= ia;
			        break;
			    case OPC_OP_DIVVF:
			        fa = popf();
			        v1 = (Vec2*)popp();
			        v.set(*v1);
			        v.div(fa);
			        pushv(v);
			        break;
			    case OPC_OP_EQFF:
			        fb = popf();
			        fa = popf();
			        pushi((int)(fa == fb));
			        break;
			    case OPC_OP_EQII:
			        ib = popi();
			        ia = popi();
			        pushi((int)(ia == ib));
			        break;
			    case OPC_OP_EQVV:
			        v2 = popv();
			        v1 = popv();
			        pushi((int)(ia == ib));
			        break;
			    case OPC_OP_GEFF:
			        fb = popf();
			        fa = popf();
			        pushi((int)(fa >= fb));
			        break;
			    case OPC_OP_GEII:
			        ib = popi();
			        ia = popi();
			        pushi((int)(ia >= ib));
			        break;
			    case OPC_OP_GTFF:
			        fb = popf();
			        fa = popf();
			        pushi((int)(fa > fb));
			        break;
			    case OPC_OP_GTII:
			        ib = popi();
			        ia = popi();
			        pushi((int)(ia > ib));
			        break;
			    case OPC_OP_LEFF:
			        fb = popf();
			        fa = popf();
			        pushi((int)(fa <= fb));
			        break;
			    case OPC_OP_LEII:
			        ib = popi();
			        ia = popi();
			        pushi((int)(ia <= ib));
			        break;
			    case OPC_OP_LTFF:
			        fb = popf();
			        fa = popf();
			        pushi((int)(fa < fb));
			        break;
			    case OPC_OP_LTII:
			        ib = popi();
			        ia = popi();
			        pushi((int)(ia < ib));
			        break;
			    case OPC_OP_MULFF:
			    	fa = popf();
			        *(((floatval*)top)-1) *= fa;
			        break;
			    case OPC_OP_MULII:
			    	ia = popi();
			        *(((int*)top)-1) *= ia;
			        break;
			    case OPC_OP_MULVF:
			        fa = popf();
			        v1 = popv();
			        v.set(*v1);
			        v.mul(fa);
			        pushv(v);
			        break;
			    case OPC_OP_NEFF:
			        fb = popf();
			        fa = popf();
			        pushi((int)(fa != fb));
			        break;
			    case OPC_OP_NEGF:
			        *(((floatval*)top)-1) = -(*((floatval*)top));
			        break;
			    case OPC_OP_NEGI:
			        *(((int*)top)-1) = -(*((int*)top));
			        break;
			    case OPC_OP_NEGV:
			        v1 = popv();
			        v.set(-v1->x, -v1->y);
			        pushv(v);
			        break;
			    case OPC_OP_NEII:
			        ib = popi();
			        ia = popi();
			        pushi((int)(ia != ib));
			        break;
			    case OPC_OP_NEVV:
			        v2 = popv();
			        v1 = popv();
			        pushi((int)(ia != ib));
			        break;
			    case OPC_OP_NOTBB:
			        ; // TODO
			        break;
			    case OPC_OP_ORBB:
			        ; // TODO
			        break;
			    case OPC_OP_SUBFF:
			    	fa = popf();
			        *(((floatval*)top)-1) -= fa;
			        break;
			    case OPC_OP_SUBII:
			    	ia = popi();
			        *(((int*)top)-1) -= ia;
			        break;
			    case OPC_OP_SUBVV:
			        v2 = (Vec2*)popp();
			        v1 = (Vec2*)popp();
			        v.set(*v1);
			        v.sub(*v2);
			        pushv(v);
			        break;
			    case OPC_OP_XORBB:
			        ; // TODO
			        break;
			}
		}
	}
Example #7
0
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }
    
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();
    
    auto bg = Sprite::create("HelloWorld.png");
    bg->setScale(this->getContentSize().width / bg->getContentSize().width,
                 this->getContentSize().height / bg->getContentSize().height);
    bg->setColor(Color3B::ORANGE);
    bg->setAnchorPoint(Vec2::ANCHOR_BOTTOM_LEFT);
    addChild(bg);
    
    
    m_gameLy = Layer::create();
    m_gameLy->setContentSize(Size(visibleSize.width, visibleSize.height * 4));
    addChild(m_gameLy, 1);
    
    
    m_hubLy = HubLayer::create();
    m_hubLy->setContentSize(Size(visibleSize.width * 0.25, visibleSize.height * 4 * 0.15));
    m_hubLy->setPosition(Vec2(1, (this->getContentSize().height - m_hubLy->getContentSize().height) / 2));
    addChild(m_hubLy, 1);
    
    m_hubLy->setgLayer(m_gameLy);
    
    
    auto lD = LayerColor::create(Color4B(255.0, 0, 0, 255.0),
                       visibleSize.width, 30);
    lD->setTag(10);
    
    lD->setPosition(Vec2(0, m_gameLy->getContentSize().height - lD->getContentSize().height));
    m_gameLy->addChild(lD);
    
    auto lP = LayerColor::create(Color4B(0, 255.0, 0, 255.0),
                                visibleSize.width, 30);
    m_gameLy->addChild(lP);
    lP->setTag(11);
    
    
    auto dispatcher = Director::getInstance()->getEventDispatcher();
    auto touchListener = EventListenerTouchOneByOne::create();
    touchListener->setSwallowTouches(true);
    touchListener->onTouchBegan = [this](Touch *touch, Event *event)->bool
    {
        m_lastMove = this->convertTouchToNodeSpace(touch);
        return true;
    };
    

    touchListener->onTouchMoved = [this](Touch *touch, Event *event)
    {
        auto location = this->convertTouchToNodeSpace(touch);
       
        Vec2 v = Vec2(location.x - m_lastMove.x, location.y - m_lastMove.y);
        Vec2 des = m_gameLy->getPosition();
        des.add(v);
        m_gameLy->setPosition(boundeEdge(des));
        m_lastMove = location;
        
    };
    touchListener->onTouchEnded = [this](Touch *touch, Event *event){};
    
    touchListener->onTouchCancelled = [this](Touch *touch, Event *event){};
    
    dispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);
    
    schedule(schedule_selector(HelloWorld::step));
    
    return true;
}