Beispiel #1
0
void wyDrawDashLine(float x1, float y1, float x2, float y2, float dashLength) {
	float dx = x2 - x1;
	float dy = y2 - y1;
	float dist = wyMath::sqrt(dx * dx + dy * dy);
	float x = dx / dist * dashLength;
	float y = dy / dist * dashLength;

	wyPoint p1 = wyp(x1, y1);
	int segments = (int)(dist / dashLength);
	int lines = (int)((float)segments / 2.0f);

	wyPoint* vertices = (wyPoint*)wyMalloc(sizeof(wyPoint) * segments);
	for(int i = 0; i < lines; i++) {
		vertices[i * 2] = p1;
		p1 = wyp(p1.x + x, p1.y + y);
		vertices[i * 2 + 1] = p1;
		p1 = wyp(p1.x + x, p1.y + y);
	}

	glEnableClientState(GL_VERTEX_ARRAY);
	glVertexPointer(2, GL_FLOAT, 0, vertices);
	glDrawArrays(GL_LINES, 0, segments);
	glDisableClientState(GL_VERTEX_ARRAY);

	wyFree(vertices);
}
Beispiel #2
0
	void populate() {
		// get texture height
		float tH2 = m_texture->getHeight() / 2;

		// get height segment step
		// two points is kept for arrow
		float tailStep = tH2 / MAX(1, m_pointCount - 3);
		float headStep = tH2 / 2;

		// update tail
		wyPoint pre = m_path[0];
		for(int i = 0; i < m_pointCount; i++) {
			// calculate height
			float height = 0;
			if(m_pointCount > 3)
				height = (i > m_pointCount - 3) ? (headStep * (m_pointCount - i - 1)) : (tailStep * i);
			
			// rotate border point along the direction
			float distance = wypDistance(pre, m_path[i]);
			float angle = (float)wypToRadian(wypSub(m_path[i], pre));
			m_vertices[i * 2] = wypRotateByAngle(wyp(pre.x + distance, pre.y + height), pre, angle);
			m_vertices[i * 2 + 1] = wypRotateByAngle(wyp(pre.x + distance, pre.y - height), pre, angle);
			
			// set texture coordinates
			m_texCoords[i * 2].x = 0.1;
			m_texCoords[i * 2].y = 0;
			m_texCoords[i * 2 + 1].x = 0.2;
			m_texCoords[i * 2 + 1].y = 1;

			// go to next
			pre = m_path[i];
		}
	}
Beispiel #3
0
wyMotionStreak::wyMotionStreak(float fade, wyTexture2D* tex, wyColor4B color, wyMotionStreakStyle style) :
		m_segThreshold(3),
		m_lastLocation(wyp(-1, -1)),
		m_currentLocation(wyp(-1, -1)),
		m_paused(false) {
	// init member
	m_pendingPoints = WYNEW vector<PendingPoint>();
	m_pendingPoints->reserve(10);

	// create ribbon by style
	switch(style) {
		case MS_STYLE_STRIP:
			m_ribbon = wyStripRibbon::make(tex, color, fade);
			break;
		case MS_STYLE_SPOT:
			m_ribbon = wySpotRibbon::make(tex, color, fade);
			break;
		case MS_STYLE_BLADE:
			m_ribbon = wyBladeRibbon::make(tex, color, fade);
			break;
		case MS_STYLE_LINE:
			m_ribbon = wyLineRibbon::make(tex, color);
			break;
	}

	// add ribbon to motion streak
    addChildLocked(m_ribbon);

    // update ribbon position
    wyTargetSelector* ts = wyTargetSelector::make(this, SEL(wyMotionStreak::update));
    wyTimer* timer = wyTimer::make(ts);
    scheduleLocked(timer);
}
Beispiel #4
0
void wyVirtualJoystick::adjustRockerPosition(float x, float y) {
	// to node space
	wyPoint p = wyp(x, y);
	p = worldToNodeSpace(p);
	wyPoint center = wyp(m_width / 2, m_height / 2);

	// check position, if in rocker radius, just set it
	// if not, connect position to center and pick the intersect point
	float distance = wypDistance(p, center);
	if(distance > m_rockerRangeRadius) {
		float ratio = m_rockerRangeRadius / distance;
		float rX = p.x - m_width / 2;
		float rY = p.y - m_height / 2;
		p.x = m_width / 2 + rX * ratio;
		p.y = m_height / 2 + rY * ratio;
	}

	// save position
	m_rockerX = p.x;
	m_rockerY = p.y;

	// set rocker position
	if(m_rocker) {
		m_rocker->setPosition(p.x, p.y);
	}

	// change degree
	m_degree = wypToDegree(wypSub(p, center));
	if(m_degree < 0)
		m_degree += 360;
}
Beispiel #5
0
void wySuck::start(wyNode* target) {
	wyGrid3DAction::start(target);

	wyPoint suck = wyp(m_positionX, m_positionY);
	m_maxDistance = MAX(m_maxDistance, wypDistance(suck, wyp(0, 0)));
	m_maxDistance = MAX(m_maxDistance, wypDistance(suck, wyp(m_target->getWidth(), 0)));
	m_maxDistance = MAX(m_maxDistance, wypDistance(suck, wyp(m_target->getWidth(), m_target->getHeight())));
	m_maxDistance = MAX(m_maxDistance, wypDistance(suck, wyp(0, m_target->getHeight())));
}
Beispiel #6
0
	virtual bool touchesBegan(wyMotionEvent& e) {
		wyPoint loc = m_box2d->worldToNodeSpace(wyp(e.x[0], e.y[0]));
		b2Vec2 p = b2Vec2(m_box2d->pixel2Meter(loc.x), m_box2d->pixel2Meter(loc.y));
		m_mouseWorld = p;

		if (m_mouseJoint != NULL) {
			return false;
		}

		// Make a small box.
		b2AABB aabb;
		b2Vec2 d;
		d.Set(0.001f, 0.001f);
		aabb.lowerBound = p - d;
		aabb.upperBound = p + d;

		// Query the world for overlapping shapes.
		QueryCallback callback(p);
		m_box2d->getWorld()->QueryAABB(&callback, aabb);

		if (callback.m_fixture) {
			b2Body* body = callback.m_fixture->GetBody();
			b2MouseJointDef md;
			md.bodyA = m_groundBody;
			md.bodyB = body;
			md.target = p;
			md.maxForce = 1000.0f * body->GetMass();
			m_mouseJoint = (b2MouseJoint*)m_box2d->getWorld()->CreateJoint(&md);
			body->SetAwake(true);

			return true;
		}

		return false;
	}
Beispiel #7
0
bool wyNode::hitTest(float x, float y) {
    wyRect rect = getBoundingBoxRelativeToWorld();
    if(m_touchCoffin) {
        wyRect r2 = m_touchCoffin->getBoundingBoxRelativeToWorld();
        rect = wyrIntersect(rect, r2);
    }
    return wyrContains(rect, wyp(x, y));
}
Beispiel #8
0
wyPoint wyBox2DPELoader::parsePoint(const char* v, bool withScale) {
	size_t len = strlen(v);
	char* tmp = (char*)wyCalloc(len + 1, sizeof(char));
	for(int i = 0, j = 0; i < len; i++) {
		if(!isspace(v[i])) {
			tmp[j++] = v[i];
		}
	}

	float w, h;
	sscanf(tmp, "{%f,%f}", &w, &h);
	wyFree(tmp);
    if(withScale)
	    return wyp(m_resScale * w, m_resScale * h);
    else
        return wyp(w, h);
}
Beispiel #9
0
wyPoint wyTMXTileMap::tmxToNodeSpace(wyPoint p) {
	switch(m_mapInfo->orientation) {
		case ORIENTATION_ORTHOGONAL:
		case ORIENTATION_HEXAGONAL:
			// ortho and hex is simple, just convert origin
			return wyp(p.x, m_height - p.y);
		case ORIENTATION_ISOMETRIC:
		{
			// iso map origin is at top vertex of (0, 0) tile, and x&y axis follows edges of that tile
			float x = m_mapWidth * m_tileWidth / 2 + p.x - p.y;
			float y = (m_mapHeight * m_tileHeight * 2 - p.x - p.y) / 2;
			return wyp(x, y);
		}
		default:
			return p;
	}
}
Beispiel #10
0
bool wySlider::touchesCancelled(wyMotionEvent& e) {
	if(m_dragging) {
		m_dragging = false;
		setValueFromLocation(worldToNodeSpace(wyp(e.x[0], e.y[0])));
	}

	return true;
}
Beispiel #11
0
wyMoveBy::wyMoveBy(float duration, float x, float y) :
		wyIntervalAction(duration),
		m_deltaX(x),
		m_deltaY(y),
		m_pinPoint(wyp(MAX_FLOAT, MAX_FLOAT)),
		m_pinDelta(0),
		m_startPositionX(0),
		m_startPositionY(0) {
}
Beispiel #12
0
wyPoint wyNode::getAbsolutePosition() {
    wyPoint p = wyp(m_positionX, m_positionY);
    wyNode* n = this;
    while(n->getParent() != NULL) {
        n = n->getParent();
        p.x += n->m_positionX;
        p.y += n->m_positionY;
    }
    return p;
}
Beispiel #13
0
wyPoint wyTransform::getInterpolationTime(float startTime, float endTime, float curTime, Interpolator& interpolator) {
	switch(interpolator.type) {
		case LINEAR:
		{
			float t = (curTime - startTime) / (endTime - startTime);
			return wyp(t, t);
		}
		case BEZIER:
		{
			wyBezierConfig bc = wybcCubic(0, 0, 1, 1, interpolator.cp1X, interpolator.cp1Y, interpolator.cp2X, interpolator.cp2Y);
			float t = (curTime - startTime) / (endTime - startTime);
			return wybcPointAt(bc, t);
		}
		case STEP:
			return curTime >= endTime ? wyp(1, 1) : wypZero;
		default:
			return wypZero;
	}
}
bool wyBox2DCollisionDetector::isCollided(wyRect& r1, wyRect& r2, wyBox2DCDResult* result) {
	// init transform 1
	sRectTrans1.SetIdentity();
	b2Vec2 v;
	v.x = pixel2Meter(r1.x + r1.width / 2);
	v.y = pixel2Meter(r1.y + r1.height / 2);
	sRectTrans1.Set(v, 0);

	// init transform 2
	sRectTrans2.SetIdentity();
	v.x = pixel2Meter(r2.x + r2.width / 2);
	v.y = pixel2Meter(r2.y + r2.height / 2);
	sRectTrans2.Set(v, 0);

	// init shape 1
	sRectPoly1.SetAsBox(pixel2Meter(r1.width) / 2, pixel2Meter(r1.height) / 2);

	// init shape 2
	sRectPoly2.SetAsBox(pixel2Meter(r2.width) / 2, pixel2Meter(r2.height) / 2);

	// collision detection
	b2Manifold manifold;
	b2CollidePolygons(&manifold, &sRectPoly1, sRectTrans1, &sRectPoly2, sRectTrans2);

	// to world coordinates
	if(manifold.pointCount > 0) {
		// write data back
		if(result) {
			// convert to world coordinate
			b2WorldManifold worldManifold;
			worldManifold.Initialize(&manifold, sRectTrans1, sRectPoly1.m_radius, sRectTrans2, sRectPoly2.m_radius);

			result->pointCount = manifold.pointCount;
			for(int i = 0; i < manifold.pointCount; i++) {
				result->points[i] = wyp(meter2Pixel(worldManifold.points[i].x), meter2Pixel(worldManifold.points[i].y));
			}

			result->normal = wyp(worldManifold.normal.x, worldManifold.normal.y);
		}
	}

	return manifold.pointCount > 0;
}
Beispiel #15
0
	virtual bool touchesMoved(wyMotionEvent& e) {
		wyPoint loc = m_box2d->worldToNodeSpace(wyp(e.x[0], e.y[0]));
		b2Vec2 p = b2Vec2(m_box2d->pixel2Meter(loc.x), m_box2d->pixel2Meter(loc.y));
		m_mouseWorld = p;

		if (m_mouseJoint) {
			m_mouseJoint->SetTarget(p);
		}

		return true;
	}
Beispiel #16
0
void wyLeftLineShrinkOut::transformTile(wyDimension pos, float distance) {
	wyQuad3D coords = getOriginalTile(pos);
	wyPoint step = wyp(m_target->getGrid()->getStepWidth(), m_target->getGrid()->getStepHeight());

	coords.bl_x += (step.x / 2) * (1.0f - distance);
	coords.br_x -= (step.x / 2) * (1.0f - distance);
	coords.tl_x += (step.x / 2) * (1.0f - distance);
	coords.tr_x -= (step.x / 2) * (1.0f - distance);

	setTile(pos, coords);
}
Beispiel #17
0
wyMoveTo::wyMoveTo(float duration, float startX, float startY, float endX, float endY) :
		wyIntervalAction(duration),
		m_endX(endX),
		m_endY(endY),
		m_startX(startX),
		m_startY(startY),
		m_pinPoint(wyp(MAX_FLOAT, MAX_FLOAT)),
		m_pinDelta(0),
		m_deltaX(endX - startX),
		m_deltaY(endY - startY) {
}
Beispiel #18
0
int wyVirtualJoystick::degree2Direction() {
	// for five direction
	static int fiveArray[] = {
			VJD_EAST,
			VJD_NORTH,
			VJD_WEST,
			VJD_SOUTH,
			VJD_EAST
	};

	// for nine directions
	static int nineArray[] = {
			VJD_EAST,
			VJD_NORTH_EAST,
			VJD_NORTH,
			VJD_NORTH_WEST,
			VJD_WEST,
			VJD_SOUTH_WEST,
			VJD_SOUTH,
			VJD_SOUTH_EAST,
			VJD_EAST
	};

	/*
	 * first we need check distance between rocker position and center, if
	 * distance is smaller than one third of rocker range radius, then neglect
	 */
	float distance = wypDistance(wyp(m_rockerX, m_rockerY), wyp(m_width / 2, m_height / 2));
	if(distance < m_rockerRangeRadius / 3.f)
		return VJD_CENTER;
	else {
		switch(m_eventStyle) {
			case VJS_FIVE_DIRECTIONS:
				return fiveArray[(m_degree + 45) / 90];
			case VJS_NINE_DIRECTIONS:
				return nineArray[(int)((m_degree + 22.5f) / 45)];
			default:
				return m_degree;
		}
	}
}
    	virtual bool touchesBegan(wyMotionEvent& event) {
    		// powered
    		if (m_Sprite->getGrid() == NULL || !m_Sprite->getGrid()->isActive()) {
				wyPoint loc = m_Sprite->worldToNodeSpace(wyp(event.x[0], event.y[0]));
				wyIntervalAction* t = wySequence::make(
						wySuck::make(0.6f, 20, 20, loc.x, loc.y),
						wyStopGrid::make(),
						NULL);
				m_Sprite->runAction(t);
    		}
			return true;
		}
Beispiel #20
0
bool wySlider::touchesBegan(wyMotionEvent& e) {
	// thumb clicked?
	if(m_thumb) {
		m_dragging = m_thumb->hitTest(e.x[0], e.y[0]);
	}

	// if not dragging, means it clicks other parts
	if(!m_dragging) {
		setValueFromLocation(worldToNodeSpace(wyp(e.x[0], e.y[0])));
	}

	return true;
}
Beispiel #21
0
wyMoveByPath::wyMoveByPath() :
		wyIntervalAction(0),
		m_pointCount(0),
		m_capacity(10),
		m_segmentStartTime(0),
		m_currentSegment(0),
		m_pinPoint(wyp(MAX_FLOAT, MAX_FLOAT)),
		m_pinDelta(0),
		m_autoRotate(false),
		m_angleDelta(0) {
	m_points = (float*)wyMalloc(m_capacity * 2 * sizeof(float));
	m_durations = (float*)wyMalloc(m_capacity * sizeof(float));
}
Beispiel #22
0
void wyMoveTo::update(float t) {
	m_target->setPosition(m_startX + m_deltaX * t, m_startY + m_deltaY * t);

	// check pin point
	if(m_pinPoint.x != MAX_FLOAT && m_pinPoint.y != MAX_FLOAT) {
		wyPoint anchor = wyp(m_target->getAnchorPointX(), m_target->getAnchorPointY());
		anchor = m_target->nodeToWorldSpace(anchor);
		float angle = wypToDegree(wypSub(m_pinPoint, anchor));
		m_target->setRotation(-angle + m_pinDelta);
	}

	// super only call callback
	wyIntervalAction::update(t);
}
Beispiel #23
0
void wySuck::update(float t) {
	// suck position
	wyPoint suck = wyp(m_positionX, m_positionY);
	
	wyDimension gridPos = wydZero;
	for(int i = 0; i <= m_gridX; i++) {
		for(int j = 0; j <= m_gridY; j++) {
			// Get original vertex
			gridPos.x = i;
			gridPos.y = j;
			wyVertex3D v = getOriginalVertex(gridPos);
			
			// get distance between grid position and suck position
			float dx = fabs(v.x - suck.x);
			float dy = fabs(v.y - suck.y);
			float d = wyMath::sqrt(dx * dx + dy * dy);

			if(d > 0) {
				// calculate offset
				float s = m_maxDistance / d;
				float valx = dx * t * s;
				float valy = dy * t * s;

				// offset vertex and make sure it is valid
				if(v.x < suck.x) {
					v.x += valx;
					v.x = MIN(suck.x, v.x);
				} else {
					v.x -= valx;
					v.x = MAX(suck.x, v.x);
				}
				if(v.y < suck.y) {
					v.y += valy;
					v.y = MIN(suck.y, v.y);
				} else {
					v.y -= valy;
					v.y = MAX(suck.y, v.y);
				}
			}

			// set new position
			setVertex(gridPos, v);
		}
	}

	// super only call callback
	wyGrid3DAction::update(t);
}
Beispiel #24
0
wyPoint wySkeletalSprite::getBonePositionRelativeToWorld(const char* boneName) {
    // basic check
    if(!m_skeleton)
        return wypZero;

    // get bone
    wyBone* bone = m_skeleton->getBone(boneName);
    if(!bone)
        return wypZero;

    // get bone node
    wyBone::State& state = bone->getState(this);
    wyAffineTransform t = state.node->getNodeToWorldTransform();
    wyPoint pos = wyp(state.x, state.y);
    return wyaTransformPoint(t, pos);
}
Beispiel #25
0
void wyMoveByPath::update(float t) {
	// find current segment
	float curTime = m_duration * t;
	float segmentTime = m_durations[m_currentSegment];
	float dt = curTime - m_segmentStartTime;
	while(dt > segmentTime && m_currentSegment < m_pointCount - 1) {
		m_currentSegment++;
		m_segmentStartTime += segmentTime;
		dt -= segmentTime;
		segmentTime = m_durations[m_currentSegment];
	}

	// update node position
	if(m_currentSegment < m_pointCount - 1) {
		float segPercent = dt / segmentTime;
		float x = m_points[m_currentSegment * 2] * (1 - segPercent) + m_points[(m_currentSegment + 1) * 2] * segPercent;
		float y = m_points[m_currentSegment * 2 + 1] * (1 - segPercent) + m_points[(m_currentSegment + 1) * 2 + 1] * segPercent;
		m_target->setPosition(x, y);
	}
	
	// update rotation
	if(m_autoRotate) {
		wyPoint d;
		d.x = m_points[(m_currentSegment + 1) * 2] - m_points[m_currentSegment * 2];
		d.y = m_points[(m_currentSegment + 1) * 2 + 1] - m_points[m_currentSegment * 2 + 1];
		float angle = -wypToDegree(d);
		angle += m_angleDelta;
		m_target->setRotation(angle);
	} else if(m_pinPoint.x != MAX_FLOAT && m_pinPoint.y != MAX_FLOAT) {
		wyPoint anchor = wyp(m_target->getAnchorPointX(), m_target->getAnchorPointY());
		anchor = m_target->nodeToWorldSpace(anchor);
		float angle = wypToDegree(wypSub(m_pinPoint, anchor));
		m_target->setRotation(-angle + m_pinDelta);
	}

	wyIntervalAction::update(t);
}
wyNodeHash* wyBox2DCollisionDetector::addNode(wyNode* node) {
	// create hash
	wyNodeHash* hash = (wyNodeHash*)wyCalloc(1, sizeof(wyNodeHash));

	// save node reference
	hash->node = node;

	// set shape size
	hash->poly.SetAsBox(pixel2Meter(node->getWidth()) / 2, pixel2Meter(node->getHeight()) / 2);
	hash->type = b2Shape::e_polygon;

	// set transform
	wyPoint pos = node->nodeToWorldSpace(wyp(node->getWidth() / 2, node->getHeight() / 2));
	b2Vec2 v;
	v.x = pixel2Meter(pos.x);
	v.y = pixel2Meter(pos.y);
	float angle = -wyMath::d2r(node->getRotation());
	hash->transform.Set(v, angle);

	// put to hash set
	wyHashSetInsert(m_nodeShapes, (size_t)node, node, hash);

	return hash;
}
Beispiel #27
0
void wyMotionStreak::addPoint(float x, float y, bool newSegment) {
	PendingPoint pp = {
			wyp(x, y), newSegment
	};
	m_pendingPoints->push_back(pp);
}
Beispiel #28
0
bool wyPageControl::touchesEnded(wyMotionEvent& e) {
	if(m_scrolling) {
		m_scrolling = false;

		if(!m_flinging) {
			int curIndex = getBestIndex();
			float start = m_vertical ? m_container->getPositionY() : m_container->getPositionX();
			wyPoint loc = wyp(e.x[0], e.y[0]);
			
			// if move is small, check page clicking
			// if move is not small, check fling
			bool clicked = false;
			if(!m_largeMove) {
				int firstIndex = getVisibleFirstIndex();
				int lastIndex = getVisibleLastIndex();
				for(int i = firstIndex; i <= lastIndex; i++) {
					wyNode* page = (wyNode*)wyArrayGet(m_pages, i);
					if(page) {
						wyRect bound = page->getBoundingBoxRelativeToWorld();
						if(wyrContains(bound, loc)) {							
							// normal center of this page
							float center = m_vertical ? (m_height / 2 - getPageCenterY(i)) : (m_width / 2 - getPageCenterX(i));
							
							// if it is current page, check whether it is clicked
							if(curIndex == i) {
								if(fabs(center - start) < DP(10)) {
									clicked = true;
									notifyOnPageClicked(i);
								}
							} 
							
							// if not 
							if(!clicked) {
								m_flinging = true;
								if(m_vertical)
									m_scroller->startScroll(0, start, 0, center - start, 1000);
								else
									m_scroller->startScroll(start, 0, center - start, 0, 1000);	
							}
							
							break;
						}
					}
				}
			} 
			
			// if not clicked, fling
			if(!clicked && !m_flinging) {
				m_flinging = true;
				if(!m_largeMove) {
					int best = getBestIndex();
					float center = m_vertical ? (m_height / 2 - getPageCenterY(best)) : (m_width / 2 - getPageCenterX(best));
					if(m_vertical)
						m_scroller->startScroll(0, start, 0, center - start, 1000);
					else
						m_scroller->startScroll(start, 0, center - start, 0, 1000);	
				} else {
					float start = m_vertical ? m_container->getPositionY() : m_container->getPositionX();
					float end = m_vertical ? (m_height / 2 - getPageCenterY(e.y[0] < m_beginY ? getRightIndex() : getLeftIndex()))
						: (m_width / 2 - getPageCenterX(e.x[0] < m_beginX ? getRightIndex() : getLeftIndex()));
					if(m_vertical)
						m_scroller->startScroll(0, start, 0, end - start, 1000);
					else
						m_scroller->startScroll(start, 0, end - start, 0, 1000);	
				}
				
				return true;	
			}
		}

		return true;
	}

	return false;
}
float wyLeftBottomTilesShrinkOut::tileTest(wyDimension pos, float time) {
	wyPoint n = wyp(m_gridX * time, m_gridY * time);
	if((n.x + n.y) == 0.0f)
		return 1.0f;
	return pow((pos.x + pos.y) / (n.x + n.y), 6);
}
bool wyBox2DCollisionDetector::isCollided(wyNode* node, wyRect& r, wyBox2DCDResult* result) {
	// init transform 2
	sRectTrans2.SetIdentity();
	b2Vec2 v;
	v.x = pixel2Meter(r.x + r.width / 2);
	v.y = pixel2Meter(r.y + r.height / 2);
	sRectTrans2.Set(v, 0);

	// init shape 2
	sRectPoly2.SetAsBox(pixel2Meter(r.width) / 2, pixel2Meter(r.height) / 2);

	// get node hash, if not, add it
	wyNodeHash* hash = (wyNodeHash*)wyHashSetFind(m_nodeShapes, (size_t)node, node);
	if(hash == NULL)
		hash = addNode(node);

	// update node1 transform
	wyPoint pos = node->nodeToWorldSpace(wyp(node->getWidth() / 2, node->getHeight() / 2));
	v.x = pixel2Meter(pos.x);
	v.y = pixel2Meter(pos.y);
	float angle = -wyMath::d2r(node->getRotation());
	hash->transform.Set(v, angle);

	// collision detection
	bool reverseNormal = false;
	b2Manifold manifold;
	switch(hash->type) {
		case b2Shape::e_polygon:
			b2CollidePolygons(&manifold, &hash->poly, hash->transform, &sRectPoly2, sRectTrans2);
			break;
		case b2Shape::e_circle:
			b2CollidePolygonAndCircle(&manifold, &sRectPoly2, sRectTrans2, &hash->circle, hash->transform);
			reverseNormal = true;
			break;
	}

	// to world coordinates
	if(manifold.pointCount > 0) {
		// write data back
		if(result) {
			// convert to world coordinate
			b2WorldManifold worldManifold;
			if(reverseNormal) {
				worldManifold.Initialize(&manifold,
										 sRectTrans2,
										 sRectPoly2.m_radius,
										 hash->transform,
										 hash->type == b2Shape::e_polygon ? hash->poly.m_radius : hash->circle.m_radius);
			} else {
				worldManifold.Initialize(&manifold,
										 hash->transform,
										 hash->type == b2Shape::e_polygon ? hash->poly.m_radius : hash->circle.m_radius,
										 sRectTrans2,
										 sRectPoly2.m_radius);
			}

			// save contact points
			result->pointCount = manifold.pointCount;
			for(int i = 0; i < manifold.pointCount; i++) {
				result->points[i] = wyp(meter2Pixel(worldManifold.points[i].x), meter2Pixel(worldManifold.points[i].y));
			}

			// save normal
			if(reverseNormal)
				result->normal = wyp(-worldManifold.normal.x, -worldManifold.normal.y);
			else
				result->normal = wyp(worldManifold.normal.x, worldManifold.normal.y);
		}
	}

	return manifold.pointCount > 0;
}