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); }
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]; } }
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); }
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; }
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()))); }
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; }
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)); }
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); }
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; } }
bool wySlider::touchesCancelled(wyMotionEvent& e) { if(m_dragging) { m_dragging = false; setValueFromLocation(worldToNodeSpace(wyp(e.x[0], e.y[0]))); } return true; }
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) { }
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; }
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; }
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; }
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); }
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) { }
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; }
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; }
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)); }
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); }
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); }
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); }
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; }
void wyMotionStreak::addPoint(float x, float y, bool newSegment) { PendingPoint pp = { wyp(x, y), newSegment }; m_pendingPoints->push_back(pp); }
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; }