Calling Variables in another function (c++) - c++

So I've gotta create a whole bunch of Variables for some colours for a customisable menu I'm making. I wanted to know if there was a way to call the variables from the first function into other functions (there are alot) These variables have to be used in over 100 locations across about 10 different functions and I really don't want to redefine all the sh*t over again every single time. (Looks messy and is a pain if I need to make changes. Heres my Menu Colour Function
Color MenuColor(int MenuAlpha_Main)
{
Color Theme;
Color Basic = Color(c_config::get().menu_color_r, c_config::get().menu_color_g, c_config::get().menu_color_b, MenuAlpha_Main);
Color Background = Color(c_config::get().menu_background_r, c_config::get().menu_background_g, c_config::get().menu_background_b, MenuAlpha_Main);
Color MiscSelectedTab_Colour = Color(c_config::get().MiscSelectedTab_r, c_config::get().MiscSelectedTab_g, c_config::get().MiscSelectedTab_b, MenuAlpha_Main);
Color MiscSelectedTab_Highlight_Colour = Color(c_config::get().MiscSelectedTab_Highlight_r, c_config::get().MiscSelectedTab_Highlight_g, c_config::get().MiscSelectedTab_Highlight_b, MenuAlpha_Main);
Color MiscUnSelectedTab_Colour = Color(c_config::get().MiscUnSelectedTab_r, c_config::get().MiscUnSelectedTab_g, c_config::get().MiscUnSelectedTab_b, MenuAlpha_Main);
Color MiscUnSelectedTab_Highlight_Colour = Color(c_config::get().MiscUnSelectedTab_Highlight_r, c_config::get().MiscUnSelectedTab_Highlight_g, c_config::get().MiscUnSelectedTab_Highlight_b, MenuAlpha_Main);
/////rainbow sync//////
static unsigned int last_time;
last_time = GetTickCount();
Color rainbow;
rainbow.FromHSV(fmod(last_time * 0.0002f, 1.f), 1.f, 0.5f);
//////////////////////
// Oh fuck, time for the customizable shit
Color MiscSelectedTab;
Color MiscSelectedTab_Highlight;
Color MiscUnSelectedTab;
Color MiscUnSelectedTab_Highlight;
if (c_config::get().menu_colour_style == 0) {
Theme = Basic; //Normal Style
}
else if (c_config::get().menu_colour_style == 1) {
Theme = rainbow; //Rainbow
}
else if (c_config::get().menu_colour_style == 2) {
//This shit is done below
}
return Theme;
if (c_config::get().menu_colour_style == 0 || c_config::get().menu_colour_style == 0 && !c_config::get().fullmenuhighlight) {
MiscSelectedTab = Background;
MiscSelectedTab_Highlight = Theme;
MiscUnSelectedTab = Background;
MiscUnSelectedTab_Highlight = Theme;
}
else if (c_config::get().menu_colour_style == 0 || c_config::get().menu_colour_style == 0 && c_config::get().fullmenuhighlight) {
MiscSelectedTab = Theme;
MiscSelectedTab_Highlight = Theme;
MiscUnSelectedTab = Theme;
MiscUnSelectedTab_Highlight = Theme;
} // MISC SUBTAB (Misc/Colours)
else if (c_config::get().menu_colour_style == 2) {
MiscSelectedTab = MiscSelectedTab_Colour;
MiscSelectedTab_Highlight = MiscSelectedTab_Highlight_Colour;
MiscUnSelectedTab = MiscUnSelectedTab_Colour;
MiscUnSelectedTab_Highlight = MiscUnSelectedTab_Highlight_Colour;
}
return MiscSelectedTab;
return MiscSelectedTab_Highlight;
return MiscUnSelectedTab;
return MiscUnSelectedTab_Highlight;
}
I'm still fairly fresh to cpp so please don't judge. And the return values would need to be referenced in a function like this
void miscsubtab(int& current_players_esp_subtab, int tab_amount, Vector _pos, int MenuAlpha_Main)
{
int in_sizew_esp_player_subtabs = GroupBoxSize_Width - 8;
static std::string ESP_Player_SubTabs_Names[2] = { "Misc", "Colours" };
for (int i = 0; i < tab_amount; i++)
{
RECT text_size2 = g_pSurface->GetTextSizeRect(Globals::SmallText, ESP_Player_SubTabs_Names[i].c_str());
int tab_area[4] = {
_pos.x + 9 + (i * (in_sizew_esp_player_subtabs / tab_amount)), _pos.y + 52 + 5,
(in_sizew_esp_player_subtabs / tab_amount), 20
};
if (GetAsyncKeyState(VK_LBUTTON) && g_pSurface->MouseInRegion(tab_area[0], tab_area[1], tab_area[2],
tab_area[3]))
current_players_esp_subtab = i;
if (current_players_esp_subtab == i)
{
g_pSurface->FilledRect(tab_area[0], tab_area[1], tab_area[2], tab_area[3], MiscSelectedTab); //HERE
g_pSurface->FilledRect(tab_area[0], tab_area[1] + tab_area[3], tab_area[2], 3, MiscSelectedTab_Highlight); //HERE
g_pSurface->DrawT(tab_area[0] + (((in_sizew_esp_player_subtabs / tab_amount) / 2) - (text_size2.right / 2)),
tab_area[1] + (tab_area[3] / 2) - (text_size2.bottom / 2),
Color(143, 143, 143, MenuAlpha_Main), Globals::SmallText, false,
ESP_Player_SubTabs_Names[i].c_str());
}
else
{
g_pSurface->FilledRect(tab_area[0], tab_area[1], tab_area[2], tab_area[3], MiscUnSelectedTab); //HERE
g_pSurface->FilledRect(tab_area[0], tab_area[1] + tab_area[3], tab_area[2], 3, MiscUnSelectedTab_Highlight); //HERE
g_pSurface->DrawT(tab_area[0] + (((in_sizew_esp_player_subtabs / tab_amount) / 2) - (text_size2.right / 2)),
tab_area[1] + (tab_area[3] / 2) - (text_size2.bottom / 2),
Color(143, 143, 143, MenuAlpha_Main), Globals::SmallText, false,
ESP_Player_SubTabs_Names[i].c_str());
}
}
}
Any help would be greatly appreciated.
Thanks -Kenny

You can define a seperate Theme struct for it and use all colors from a Theme variable.
class Theme {
public:
enum Style {BASIC, RAINBOW, CUSTOM};
Style style;
Color MiscSelectedTab;
Color MiscSelectedTab_Highlight;
Color MiscUnSelectedTab;
Color MiscUnSelectedTab_Highlight;
}
Theme MenuColor(int MenuAlpha_Main)
{
Theme theme;
...
if (c_config::get().menu_colour_style == 0) {
theme.style = Theme::BASIC; //Normal Style
}
else if (c_config::get().menu_colour_style == 1) {
theme.style = Theme::RAINBOW; //Rainbow
}
else if (c_config::get().menu_colour_style == 2) {
theme.style = Theme::CUSTOM;
//This shit is done below
}
....
return theme;
}
...
Theme myTheme = MenuColor(5);
myTheme.MiscSelectedTab;
myTheme.MiscSelectedTab_Highlight;
myTheme.MiscUnSelectedTab;
myTheme.MiscUnSelectedTab_Highlight;

Related

Dynamic Light effect with Cocos2d-x 4.0 and C++

I've been trying to create a dynamic light effect with cocos2d-x, but I cannot find a good tutorial for the 4.0 version.
For the context, I'm developping a top-down game for as a personnal project. The light would spread directly in front of the player like a flash-light, lighting every object in front of him and "colliding" with the walls and entities
The Shader hint
I've found multiple repos creating a custom light effect with cocos2d-x, but they all use the 3.0 version. The 4.0 version changed how the OpenGL code is managed in the Cocos backend.
Here's the repos I've found :
https://github.com/CodeAndWeb/cocos2d-x-dynamic-lighting
https://github.com/zerodarkzone/Cocos2d-x-lights
https://github.com/wantnon2/EffectNodes-for-cocos2dx
I've also read the Cocos2d-x Gitbook which explains what exactly changed in the CCSprite file.
Since I'm a beginner to Cocos2d-x and shader rendering, I did not understand what I had to change to make the old repos work ..
The polygon hint
I tried to create a VisionZone that would be a Cocos2d-x Node. The node would have a physic body colliding with the walls. On collision, the shape would update and adapt its shape.
Here's what the code would look like :
VisionZone.h
class VisionZone : public Node {
public:
static std::vector<Vec2> sm_shapeCollisionPoints;
static VisionZone *create(Vec2 origin, int visionDetail);
bool init() override;
void update(float delta) override;
void UpdateWithPlayer(Vec2 playerPos);
private:
void CreateNewPhysicBody(std::vector<Vec2> &points);
void UpdateShapeAndRedraw();
static bool IsInLine(Vec2 segmentStart, Vec2 segmentEnd, Vec2 point);
void CompareWithContactPoints();
void Rotate();
std::vector<Vec2> m_nonCollidedSegmentsEnds;
std::vector<Vec2> m_collidedSegmentsEnds;
Vec2 m_origin;
DrawNode *m_pVisionZoneDrawer;
int m_visionDetail;
VisionZone.cpp
std::vector<Vec2> VisionZone::sm_shapeCollisionPoints = {};
VisionZone *VisionZone::create(Vec2 origin, int visionDetail) {
auto *_obj = new(std::nothrow) VisionZone();
if (_obj && _obj->init()) {
_obj->m_origin = origin;
_obj->m_visionDetail = visionDetail;
int mid = std::floor(_obj->m_visionDetail * 0.5);
for (int i = -(mid); i <= mid; i++) {
_obj->m_nonCollidedSegmentsEnds.emplace_back(
static_cast<float>(_obj->m_origin.x + float(i) * 1.3f), _obj->m_origin.y + 300
);
}
_obj->m_collidedSegmentsEnds = _obj->m_nonCollidedSegmentsEnds;
std::vector<Vec2> _points = _obj->m_nonCollidedSegmentsEnds;
_points.emplace_back(_obj->m_origin);
_obj->CreateNewPhysicBody(_points);
} else
CC_SAFE_DELETE(_obj);
return _obj;
}
bool VisionZone::init() {
if (!Node::init()) return false;
m_pVisionZoneDrawer = DrawNode::create();
m_pVisionZoneDrawer->setPosition(m_origin);
assert(m_pVisionZoneDrawer);
addChild(m_pVisionZoneDrawer);
return true;
}
void VisionZone::update(float delta) {
Node::update(delta);
CompareWithContactPoints();
Rotate();
UpdateShapeAndRedraw();
}
void VisionZone::UpdateWithPlayer(Vec2 playerPos) {
m_origin = playerPos;
setPosition(m_origin);
}
void VisionZone::CreateNewPhysicBody(std::vector<Vec2> &points) {
points.push_back(m_origin);
PhysicsBody *_body = PhysicsBody::createEdgePolygon(
&points.front(),
int(points.size()),
PHYSICSBODY_MATERIAL_DEFAULT,
1
);
_body->setCategoryBitmask(vision_zone_collision_bitmask);
_body->setCollisionBitmask(map_collision_bitmask);
_body->setContactTestBitmask(true);
_body->setDynamic(false);
setPhysicsBody(_body);
}
bool VisionZone::IsInLine(Vec2 segmentStart, Vec2 segmentEnd, Vec2 point) {
float _startToPoint = sqrt(pow((segmentStart.x - point.x), 2) + pow((segmentStart.y - point.y), 2));
float _pointToEnd = sqrt(pow((point.x - segmentEnd.x), 2) + pow((point.y - segmentEnd.y), 2));
float _startToEnd = sqrt(pow((segmentStart.x - segmentEnd.x), 2) + pow((segmentStart.y - segmentEnd.y), 2));
return (_startToPoint + _pointToEnd == _startToEnd);
}
void VisionZone::CompareWithContactPoints() {
if (sm_shapeCollisionPoints.empty()) {
m_collidedSegmentsEnds = {m_origin, m_nonCollidedSegmentsEnds.front(), m_nonCollidedSegmentsEnds.back()};
return;
}
for (Vec2 &_nonCollidedEnd: m_nonCollidedSegmentsEnds) {
for (Vec2 &_contactPoint: sm_shapeCollisionPoints) {
if (IsInLine(m_origin, _nonCollidedEnd, _contactPoint)) {
Vec2 _midPoint = (m_nonCollidedSegmentsEnds.front() + m_nonCollidedSegmentsEnds.back()) / 2;
if (IsInLine(m_nonCollidedSegmentsEnds.front(), _midPoint, _contactPoint)) {
m_collidedSegmentsEnds = {
m_origin, sm_shapeCollisionPoints.front(), sm_shapeCollisionPoints.back(),
m_nonCollidedSegmentsEnds.back()
};
} else if (IsInLine(_midPoint, m_nonCollidedSegmentsEnds.back(), _contactPoint)) {
m_collidedSegmentsEnds = {
m_origin, m_nonCollidedSegmentsEnds.front(), sm_shapeCollisionPoints.front(),
sm_shapeCollisionPoints.back()
};
}
}
}
}
}
void VisionZone::Rotate() {
float _distanceX = InputManager::GetCursorPosX() - getPositionX();
float _distanceY = InputManager::GetCursorPosY() - getPositionY();
float _angle = atan2(_distanceY, _distanceX) * 180.f / static_cast<float>(M_PI);
setRotation(_angle);
}
void VisionZone::UpdateShapeAndRedraw() {
PhysicsShape *_newShape = getPhysicsBody()->addShape(PhysicsShapePolygon::create(
m_collidedSegmentsEnds.data(), int(m_collidedSegmentsEnds.size()))
);
assert(_newShape);
m_pVisionZoneDrawer->clear();
m_pVisionZoneDrawer->drawSolidPoly(
&m_collidedSegmentsEnds.front(),
m_collidedSegmentsEnds.size(),
Color4F(1.f, 0.94, 0.7, 1)
);
}
CollisionManager.cpp
#include "CollisionManager.h"
#include "Utility/Bitmasks.h"
USING_NS_CC;
EventListenerPhysicsContact *CollisionManager::m_contactListener = nullptr;
void CollisionManager::Init() {
m_contactListener = EventListenerPhysicsContact::create();
m_contactListener->onContactBegin = [](PhysicsContact &contact) { return ContactBeginCallback(contact); };
m_contactListener->onContactSeparate = [](PhysicsContact &contact) { return ContactSeparateCallback(contact); };
}
bool CollisionManager::ContactBeginCallback(PhysicsContact &contact) {
PhysicsBody *_bodyA = contact.getShapeA()->getBody();
PhysicsBody *_bodyB = contact.getShapeB()->getBody();
const bool visionAndWallCondition = ((_bodyA->getCategoryBitmask() == vision_zone_collision_bitmask &&
_bodyB->getCategoryBitmask() == map_collision_bitmask) ||
(_bodyB->getCategoryBitmask() == vision_zone_collision_bitmask &&
_bodyA->getCategoryBitmask() == map_collision_bitmask));
if (visionAndWallCondition) {
for (Vec2 _p: contact.getContactData()->points) VisionZone::sm_shapeCollisionPoints.push_back(_p);
return true;
}
return false;
}
bool CollisionManager::ContactSeparateCallback(PhysicsContact &contact) {
PhysicsBody *_bodyA = contact.getShapeA()->getBody();
PhysicsBody *_bodyB = contact.getShapeB()->getBody();
const bool visionAndWallCondition = ((_bodyA->getCategoryBitmask() == vision_zone_collision_bitmask &&
_bodyB->getCategoryBitmask() == map_collision_bitmask) ||
(_bodyB->getCategoryBitmask() == vision_zone_collision_bitmask &&
_bodyA->getCategoryBitmask() == map_collision_bitmask));
if (visionAndWallCondition) {
VisionZone::sm_shapeCollisionPoints.clear();
return true;
}
return false;
}
GameLayer.cpp
bool GameLayer::init() {
if (!Layer::init()) return false;
CollisionManager::Init();
_eventDispatcher->addEventListenerWithSceneGraphPriority(CollisionManager::GetContactListener(), this);
// ... SOME CODE ... //
m_visionZone = VisionZone::create(player->getPosition(), 100);
addChild(m_visionZone, 1);
return true;
}
void GameLayer::update(float delta) {
Node::update(delta);
m_visionZone->UpdateWithPlayer(m_player->getPosition());
}
I am not sure about this method though ... I feels like it is not optimal at all ?
Really curious to have some feedback on this, thanks in advance, sorry for the quantity of code :)
Let me know if you need more informations, code or links

Multiple convex shape corner connection

I have an immutable array structure holding convex shapes as in the image above (they may vary in size and count, however they are always convex and never overlapping). What I want to do is connect the corners between them that can be connected without overlaping any edge, as in the image bellow where the blue lines represent the connections.
The data I have available are data structures holding the corner positions in the convex shapes, represented as a Vector structure similar to the following:
class Vector2
{
public:
float x, y;
}
The convex shape structure looks something like this:
class ConvexShape
{
public:
std::vector<Vector2> edges;
}
What I want to return from the function is an std::vector of a structure similar to the following:
class LinkedVector2 : public Vector2
{
public:
std::vector<LinkedVector2*> links;
}
So each linked vector is supposed to have a pointer to each other linked vector it is connected to.
The final function will thereby have this format:
std::vector<LinkedVector>* generateLinks(const std::vector<ConvexShape>& shapes)
{
std::vector<LinkedVector> links{ new std::vector<LinkedVector>{} };
// Create a linked vector for each shape's corner.
// Calculate links.
return links;
}
All of these links I then want to save for use in a later function which connects two points to the already linked shapes, along the lines of this:
The function should not alter the already existing connections and should look something like this:
// Argument 'links' will contain the previously generated links.
std::vector<LinkedVector>* connectPoints(const Vector2& a, const Vector2& b, const std::vector<LinkedVector>& links)
{
std::vector<LinkedVector>* connections{ new std::vector<LinkedVector>{} };
// Add old links to 'connections'.
// Connect the new links to the old.
// Add the new links to 'connections'.
return connections;
}
Could someone help me with how this could be done?
This is a description for an algorithm with example implementation to get you going.
Step 1
Preprocess every edge of the two shapes (s0 and s1) and extract the following information:
Distances from every edge in one shape to the vertices in the other
An ordered set of the vertices in one shape facing towards the other
Finding the distances is an exhaustive task (O(|V(s0)| * |V(s1)|)), it is also very cheap (line-point distance) and embarrassingly parallelisable. The facing vertices are found using the distances from above:
Start with the first vertex on the first shape, where the other shape is completely outside of its two adjacent edges (i.e. for any adjacent edge there exist outside values in its distances).
Since the facing set is a unique sequential set of vertices for convex polygons, continue adding vertices...
...until you reach a vertex where all vertices from the other shape lie inside of its adjacent edges
Doing this for both sides results in two sequences of facing vertices in each shape (the green dots per shape):
Step 2
To connect the two facing sets a scanline approach can be used:
In the ordered set of facing vertices the first vertex from one shape is always in line of sight of the last vertex from the other shape (first and last in case the shapes are oriented the same). From there we'll search sequentially, using the angle criteria from above for both the query from the first and the candidate vertex from the other shape, in the facing set to initialise our loop.
Looping sequentially over the facing vertices of the first shape, remove vertices that have broken line of sight (red line) and add vertices that came within line of sight (green line).
Step 3
Connecting the two outside points with the shapes is equivalent to finding the facing set of one shape in step 1 but instead of to another shape now there are only those individual outside points.
I've implemented step 1 and 2 in the following little browser demo as a prove of concept:
Click on the canvas and drag to move the camera
Click inside a shape and drag to move the shape
(function(canvas) {
function v2(x, y) { return { x: x, y: y }; }
function v2mul(lhs, rhs) { lhs.x *= rhs.x; lhs.y *= rhs.y; }
function v2subed(lhs, rhs) { return v2(lhs.x - rhs.x, lhs.y - rhs.y); }
function v2dot(lhs, rhs) { return lhs.x * rhs.x + lhs.y * rhs.y; }
function v2normalized(v) { var len = Math.sqrt(v2dot(v, v)); if(len < 1e-7) len = 1; return v2(v.x / len, v.y / len); }
function v2perped(v) { return v2(-v.y, v.x); }
// Line from origin o : v2 and direction d : v2
function Line(o, d) {
this.o = o;
this.d = d;
}
// Signed distance to a point v : v2, in units of direction this.d
Line.prototype.distance = function(v) {
var o = v2subed(v, this.o);
var d = v2perped(this.d);
return v2dot(o, d);
};
// A polygon is made up of a sequence of points (arguments[i] : v2)
function Polygon() {
this.positions = [].slice.call(arguments);
}
// Transform polygon to new base [bx, by] and translation t
Polygon.prototype.transform = function(bx, by, t) {
this.positions.forEach(function(v) {
var x = bx.x * v.x + by.x * v.y + t.x;
var y = bx.y * v.x + by.y * v.y + t.y;
v.x = x;
v.y = y;
});
};
// Naive point inside polygon test for polygon picking
Polygon.prototype.isInside = function(v) {
if(this.positions.length < 3)
return false;
var o0 = this.positions[this.positions.length - 1];
for(var i = 0, imax = this.positions.length; i < imax; ++i) {
var o1 = this.positions[i];
var line = new Line(o0, v2normalized(v2subed(o1, o0)));
if(line.distance(v) <= 0)
return false;
o0 = o1;
}
return true;
};
// A camera positioned at eye : v2
function Camera(eye) {
this.eye = eye;
}
// Prepare temporaries for screen conversions
Camera.prototype.prepare = function(w, h) {
this.screen = {
off: v2(w / 2, h / 2),
};
};
Camera.prototype.toScreenX = function(x) { return x + this.screen.off.x - this.eye.x; }
Camera.prototype.toScreenY = function(y) { return this.screen.off.y - y + this.eye.y; }
Camera.prototype.fromScreenX = function(x) { return x - this.screen.off.x + this.eye.x; }
Camera.prototype.fromScreenY = function(y) { return this.screen.off.y - y + this.eye.y; }
Camera.prototype.toScreen = function(v) { return v2(this.toScreenX(v.x), this.toScreenY(v.y)); };
Camera.prototype.fromScreen = function(v) { return v2(this.fromScreenX(v.x), this.fromScreenY(v.y)); }
// Compute the distances of the line through e0 in p0 to each vertex in p1
// #post e0.distances.length === p1.positions.length
function computeEdge(e0, p0, p1) {
var line = new Line(p0.positions[e0.start], v2normalized(v2subed(p0.positions[e0.end], p0.positions[e0.start])));
var distances = [];
p1.positions.forEach(function(v) { distances.push(line.distance(v)); });
e0.line = line;
e0.distances = distances;
return e0;
}
// Find vertices in a convex polygon p0 that face p1
// #pre edges.length === p0.positions.length
function computeFacing(edges, p0, p1) {
var facing = [];
var count0 = p0.positions.length;
var count1 = p1.positions.length;
function isFacingVertex(i0) {
var e0 = edges[(i0 + count0 - 1) % count0];
var e1 = edges[i0];
for(var i1 = 0; i1 < count1; ++i1)
if(e0.distances[i1] < 0 || e1.distances[i1] < 0)
return true;
return false;
}
// Find the first vertex in the facing set of two non-intersecting, convex polygons
for(var i0 = 0; i0 < count0; ++i0) {
// For the first chance facing vertex
if(isFacingVertex(i0)) {
if(i0 === 0) {
// Search backwards here, s.t. we can complete the loop in one sitting
var iStart = count0;
for(; iStart > 1 && isFacingVertex(iStart - 1); --iStart);
while(iStart < count0)
facing.push(iStart++);
}
facing.push(i0++);
// In a convex polygon the (single) set of facing vertices is sequential
while(i0 < count0 && isFacingVertex(i0))
facing.push(i0++);
break;
}
}
return facing;
}
// Preprocesses the convex polygon p0 building the edges and facing lists
function preprocessPolygon(p0, p1) {
var result = {
edges: [],
facing: null,
};
for(var i = 0, imax = p0.positions.length; i < imax; ++i)
result.edges.push(computeEdge({ start: i, end: (i + 1) % imax }, p0, p1));
result.facing = computeFacing(result.edges, p0, p1);
return result;
}
// Scanline-approach to find all line of sight connections between the facing vertices of two preprocessed convex polygons p0 : Polygon and p1 : Polygon
// Output is prep.connections where prep.connections[i] : { v0, v1 } describes an unobstructed line of sight edge between vertex index v0 in p0 and v1 in p1
function computeConnections(prep, p0, p1) {
var connections = [];
var facing1count = prep.p1.facing.length;
// For oriented polygons the first facing vertex in p0 must surely face the last facing vertex in p1
var facing1begin = facing1count - 1, facing1end = facing1count;
prep.p0.facing.forEach(function(v0) {
function isConnectingVertex(v1) {
// Is v1 outside of adjacent edge-lines from v0?
var count0 = prep.p0.edges.length;
var ep = prep.p0.edges[(v0 + count0 - 1) % count0];
var en = prep.p0.edges[v0];
if(!(ep.distances[v1] < 0 || en.distances[v1] < 0)) return false;
// Is v0 outside of adjacent edge-lines from v1?
var count1 = prep.p1.edges.length;
ep = prep.p1.edges[(v1 + count1 - 1) % count1];
en = prep.p1.edges[v1];
return ep.distances[v0] < 0 || en.distances[v0] < 0;
}
// Throw away vertices that are no longer facing the current vertex
for(; facing1end > 0 && !isConnectingVertex(prep.p1.facing[facing1end - 1]); --facing1end);
// Add newly facing vertices
for(; facing1begin > 0 && isConnectingVertex(prep.p1.facing[facing1begin - 1]); --facing1begin);
// Generate the connections in facing range
for(var facing1 = facing1begin; facing1 < facing1end; ++facing1)
connections.push({ v0: v0, v1: prep.p1.facing[facing1] });
});
prep.connections = connections;
}
function process(prep, p0, p1) {
delete prep.p0;
delete prep.p1;
delete prep.connections;
prep.p0 = preprocessPolygon(p0, p1);
prep.p1 = preprocessPolygon(p1, p0);
computeConnections(prep, p0, p1);
}
var polygons = null;
var prep = null;
var camera = null;
var ui = null;
function reset() {
polygons = [
new Polygon(v2(25, -75), v2(50, -175), v2(140, -225), v2(255, -200), v2(195, -65), v2(140, -40)),
new Polygon(v2(400, -100), v2(295, -70), v2(260, -80), v2(310, -220), v2(425, -230)),
];
// Scale to a fitting size and move to center
var bx = v2(0.5, 0), by = v2(0, 0.5), off = v2(-120, 70);
polygons[0].transform(bx, by, off);
polygons[1].transform(bx, by, off);
prep = {};
camera = new Camera(v2(0, 0));
ui = { pickedPolygon: -1 };
update();
draw();
}
function update() {
// Reprocess polygons
process(prep, polygons[0], polygons[1]);
}
function draw() {
var g = canvas.getContext("2d");
var w = canvas.width;
var h = canvas.height;
camera.prepare(w, h);
g.fillStyle = "linen";
g.fillRect(0, 0, w, h);
var iPick = 0;
polygons.forEach(function(polygon) {
var highlight = iPick++ === ui.pickedPolygon;
var positions = polygon.positions;
if(positions.length > 2) {
g.beginPath();
g.lineWidth = highlight ? 2 : 1;
g.strokeStyle = "black";
var pLast = camera.toScreen(positions[positions.length - 1]);
g.moveTo(pLast.x, pLast.y);
positions.forEach(function(pos) {
var pScreen = camera.toScreen(pos);
g.lineTo(pScreen.x, pScreen.y);
});
g.stroke();
}
});
prep.connections.forEach(function(connection) {
var v0 = camera.toScreen(polygons[0].positions[connection.v0]);
var v1 = camera.toScreen(polygons[1].positions[connection.v1]);
g.beginPath();
g.lineWidth = 2;
g.strokeStyle = "cyan";
g.moveTo(v0.x, v0.y);
g.lineTo(v1.x, v1.y);
g.stroke();
});
}
(function(c) {
reset();
var dragStartPos = null, dragLastPos = null;
var pickedPolygon = null;
var cameraStartPos = v2(0, 0);
function toScreen(client) {
var rect = c.getBoundingClientRect();
return v2(client.x - rect.left, client.y - rect.top);
}
function startDragging(x, y) {
dragStartPos = v2(x, y);
dragLastPos = v2(x, y);
if(pickedPolygon !== null) {
// Nothing to prepare
} else {
cameraStartPos.x = camera.eye.x;
cameraStartPos.y = camera.eye.y;
}
}
function continueDragging(x, y) {
if(pickedPolygon !== null) {
var dx = x - dragLastPos.x, dy = -(y - dragLastPos.y);
pickedPolygon.transform(v2(1, 0), v2(0, 1), v2(dx, dy));
update();
} else {
var dx = -(x - dragStartPos.x), dy = y - dragStartPos.y;
camera.eye.x = cameraStartPos.x + dx;
camera.eye.y = cameraStartPos.y + dy;
}
dragLastPos.x = x;
dragLastPos.y = y;
}
function stopDragging() {
dragStartPos = null;
dragLastPos = null;
if(pickedPolygon !== null) {
// Nothing to do here...
} else {
cameraStartPos.x = 0;
cameraStartPos.y = 0;
}
}
c.onmousemove = function(e) {
if(dragStartPos !== null)
continueDragging(e.clientX, e.clientY);
else {
pickedPolygon = null;
var iPick = 0;
var cursorPos = camera.fromScreen(toScreen(v2(e.clientX, e.clientY)));
for(var imax = polygons.length; iPick < imax; ++iPick) {
if(polygons[iPick].isInside(cursorPos)) {
pickedPolygon = polygons[iPick];
break;
}
}
ui.pickedPolygon = pickedPolygon !== null ? iPick : -1;
}
draw();
};
c.onmouseleave = function(e) {
if(dragStartPos !== null)
stopDragging();
pickedPolygon = null;
ui.pickedPolygon = -1;
draw();
};
c.onmousedown = function(e) {
if(e.button === 0)
startDragging(e.clientX, e.clientY);
draw();
};
c.onmouseup = function(e) {
if(e.button === 0 && dragStartPos !== null)
stopDragging();
draw();
};
})(canvas);
})(document.getElementById("screen"));
<canvas id="screen" width="300" height="300"></canvas>

How to make trigger area in Cocos2d

I am doing a Flappy Bird game following some tutorials. To count up the score, I have set PhysicsBody among the score area, but it is just like a Rigibody in Unity, other objects cannot get through it.
You can take reference at https://www.youtube.com/watch?v=3zGTCGgwt_U&list=PLRtjMdoYXLf7GSD9crXIjMQiRuIZ7mUVp&index=12, it is the result that I want. I followed it but I don't know why here comes a difference.
In my situation, the score line blocks my flying bird. As the score lines and pipes are moving backward, my flappy bird is pushed by the score line until it reaches the screen edge and turns out a gameover.
I want something like a Trigger Collider in Unity. Is there any similar thing in cocos2d?
Also attach my code here, it spawns the pipes as well as the score line:
void Pipe::Spawn(Layer* pipeLayer) {
auto upperPipe = Sprite::create("pipe_upper.png");
upperPipe->setAnchorPoint(Vec2(0.5,0));
upperPipe->setScale(spriteScale);
auto upperPipeBody = PhysicsBody::createBox(upperPipe->getContentSize());
upperPipeBody->setDynamic(false);
upperPipeBody->setCollisionBitmask(OBSTACLE_COLLISION_BITMASK);
upperPipeBody->setContactTestBitmask(true);
upperPipe->setPhysicsBody(upperPipeBody);
auto bottomPipe = Sprite::create("pipe_bottom.png");
bottomPipe->setAnchorPoint(Vec2(0.5,1));
bottomPipe->setScale(spriteScale);
auto bottomPipeBody = PhysicsBody::createBox(bottomPipe->getContentSize());
bottomPipeBody->setDynamic(false);
bottomPipeBody->setCollisionBitmask(OBSTACLE_COLLISION_BITMASK);
bottomPipeBody->setContactTestBitmask(true);
bottomPipe->setPhysicsBody(bottomPipeBody);
float randomPosIndex = CCRANDOM_0_1();
if (randomPosIndex < PIPE_BOTTOM_THRESHOLD) {
randomPosIndex = PIPE_BOTTOM_THRESHOLD;
}
else if (randomPosIndex > PIPE_UPPER_THRESHOLD) {
randomPosIndex = PIPE_UPPER_THRESHOLD;
}
float gapHeight = Sprite::create("flappybird1_01.png")->getContentSize().height * spriteScale * PIPE_GAP_INDEX;
Size visibleSize = Director::getInstance()->getVisibleSize();
//setup bottom pipe
bottomPipe->setPosition(Point(visibleSize.width, visibleSize.height * randomPosIndex));
//setup upper pipe
upperPipe->setPosition(Point(visibleSize.width, bottomPipe->getPositionY() + gapHeight));
//setup score area
auto scoreNode = Node::create();
auto scoreNodeBody = PhysicsBody::createBox(Size(1, gapHeight));
scoreNodeBody->setDynamic(false);
scoreNodeBody->setCollisionBitmask(SCORE_COLLISION_BITMASK);
scoreNodeBody->setContactTestBitmask(true);
scoreNode->setPhysicsBody(scoreNodeBody);
scoreNode->setPosition(Point(bottomPipe->getPositionX(), bottomPipe->getPositionY() + gapHeight / 2));
auto bottomPipeAction = RepeatForever::create(MoveBy::create(1, Vec2(-PIPE_MOVE_SPEED, 0)));
auto upperPipeAction = RepeatForever::create(MoveBy::create(1, Vec2(-PIPE_MOVE_SPEED, 0)));
auto scoreNodeAction = RepeatForever::create(MoveBy::create(1, Vec2(-PIPE_MOVE_SPEED, 0)));
bottomPipe->runAction(bottomPipeAction);
upperPipe->runAction(upperPipeAction);
scoreNode->runAction(scoreNodeAction);
pipeLayer->addChild(bottomPipe);
pipeLayer->addChild(upperPipe);
pipeLayer->addChild(scoreNode);
CCLOG("Spawn Pipe");
}
Credits to ryemoss's reference. Simply return false in the collision callback function solves everything!
bool GameScene::onContactBegin(PhysicsContact &contact)
{
PhysicsBody* a = contact.getShapeA()->getBody();
PhysicsBody* b = contact.getShapeB()->getBody();
if ( (a->getCollisionBitmask() == FLAPPYBIRD_COLLISION_BITMASK && b->getCollisionBitmask() == OBSTACLE_COLLISION_BITMASK) ||
(b->getCollisionBitmask() == FLAPPYBIRD_COLLISION_BITMASK && a->getCollisionBitmask() == OBSTACLE_COLLISION_BITMASK)
)
{
auto gameoverScene = GameOverScene::createScene();
Director::getInstance()->replaceScene(TransitionFade::create(SCENE_TRANSITION_DURATION, gameoverScene));
}
else if ((a->getCollisionBitmask() == FLAPPYBIRD_COLLISION_BITMASK && b->getCollisionBitmask() == SCORE_COLLISION_BITMASK) ||
(b->getCollisionBitmask() == FLAPPYBIRD_COLLISION_BITMASK && a->getCollisionBitmask() == SCORE_COLLISION_BITMASK))
{
score++;
CCLOG("Score Count: %i", score);
return false;
}
return true;
}

Sprite collision with tile map

So, I'm trying to build my own game engine and my first project is creating a pacman clone. I've worked out how to create the tilemap and move pacman around on it. But I've having issues creating a collision detector with the tilemap. Particularly the issue is that the collision detects fine for any tiles north of the current location, however it thinks the tile below the current location is actually 1 tile larger than normal. And 0 collision exists for tiles east and west of the current location. I'm confused because the collision works for the north tile... but I'm using the same logic for the other directions and it's not working.
The logic I am using is that 'okay' tiles to move into are value 0. Any other tile is not able for movement.
Here is the code I'm using for the actual wall collision:
//checks for a sprite colliding with a wall tile
//direction refers to 1=North, 2=South, 3=West, 4=East
bool Wall_Collision(SPRITE sprite, int direction)
{
//grab center of sprite
Posx = sprite.x + Sprite_Radius;
Posy = sprite.y + Sprite_Radius;
//create rectangle for the sprite
RECT spriteRect;
spriteRect.left = (long)sprite.x;
spriteRect.top = (long)sprite.y;
spriteRect.right = (long)sprite.x + sprite.width * sprite.scaling;
spriteRect.bottom = (long)sprite.y + sprite.height * sprite.scaling;
//recover North tile info
int N_posx, N_posy;
int N_tilex, N_tiley;
int N_tilevalue;
N_posx = Posx / TILEWIDTH;
N_posy = (Posy - TILEHEIGHT) / TILEHEIGHT;
N_tilex = N_posx * TILEWIDTH;
N_tiley = N_posy * TILEHEIGHT;
N_tilevalue = MAPDATA[(N_posy * MAPWIDTH + N_posx)];
//create rectangle for tile North of sprite center
RECT northRect;
northRect.left = N_tilex;
northRect.top = N_tiley;
northRect.right = N_tilex + TILEWIDTH;
northRect.bottom = N_tiley + TILEHEIGHT;
//recover South tile info
int S_posx, S_posy;
int S_tilex, S_tiley;
int S_tilevalue;
S_posx = Posx / TILEWIDTH;
S_posy = (Posy + TILEHEIGHT) / TILEHEIGHT;
S_tilex = S_posx * TILEWIDTH;
S_tiley = S_posy * TILEHEIGHT;
S_tilevalue = MAPDATA[(S_posy * MAPWIDTH + S_posx)];
//create rectangle for tile South of sprite center
RECT southRect;
southRect.left = S_tilex;
southRect.top = S_tiley;
southRect.right = S_tilex + TILEWIDTH;
southRect.bottom = S_tiley + TILEHEIGHT;
//recover West tile info
int W_posx, W_posy;
int W_tilex, W_tiley;
int W_tilevalue;
W_posx = (Posx - TILEWIDTH) / TILEWIDTH;
W_posy = Posy / TILEHEIGHT;
W_tilex = W_posx * TILEWIDTH;
W_tiley = W_posy * TILEHEIGHT;
W_tilevalue = MAPDATA[(W_posy * MAPWIDTH + W_posx)];
//create rectangle for tile West of sprite center
RECT westRect;
westRect.left = W_tilex;
westRect.top = W_tiley;
westRect.right = W_tilex + TILEWIDTH;
westRect.bottom = W_tiley + TILEHEIGHT;
//recover East tile info
int E_posx, E_posy;
int E_tilex, E_tiley;
int E_tilevalue;
E_posx = (Posx + TILEWIDTH) / TILEWIDTH;
E_posy = Posy / TILEHEIGHT;
E_tilex = E_posx * TILEWIDTH;
E_tiley = E_posy * TILEHEIGHT;
E_tilevalue = MAPDATA[(E_posy * MAPWIDTH + E_posx)];
//create rectangle for tile East of sprite center
RECT eastRect;
eastRect.left = E_tilex;
eastRect.top = E_tiley;
eastRect.right = E_tilex + TILEWIDTH;
eastRect.bottom = E_tiley + TILEHEIGHT;
RECT dest; //ignored
//check North collision
if (direction == 1 && N_tilevalue != 0)
{
return IntersectRect(&dest, &spriteRect, &northRect);
}
else return false;
//check South collision
if (direction == 2 && S_tilevalue != 0)
{
return IntersectRect(&dest, &spriteRect, &southRect);
}
else return false;
//check West collision
if (direction == 3 && W_tilevalue != 0)
{
return IntersectRect(&dest, &spriteRect, &westRect);
}
else return false;
//check East collision
if (direction == 4 && E_tilevalue != 0)
{
return IntersectRect(&dest, &spriteRect, &eastRect);
}
else return false;
}
And then the context I'm using the function to move the player sprite:
void MovePacman()
{
if (Wall_Collision(pacman, 1))
{
pacman.y -= pacman.vely;
pacman.vely = 0.0f;
}
else
{
if (Key_Down(DIK_UP))
{
pacman.vely = -0.2f;
pacman.velx = 0.0f;
}
}
if (Wall_Collision(pacman, 2))
{
pacman.y -= pacman.vely;
pacman.vely = 0.0f;
}
else
{
if (Key_Down(DIK_DOWN))
{
pacman.vely = 0.2f;
pacman.velx = 0.0f;
}
}
if (Wall_Collision(pacman, 3))
{
pacman.x -= pacman.velx;
pacman.velx = 0.0f;
}
else
{
if (Key_Down(DIK_LEFT))
{
pacman.velx = -0.2f;
pacman.vely = 0.0f;
}
}
if (Wall_Collision(pacman, 4))
{
pacman.x -= pacman.velx;
pacman.velx = 0.0f;
}
else
{
if (Key_Down(DIK_RIGHT))
{
pacman.velx = 0.2f;
pacman.vely = 0.0f;
}
else;
}
if (pacman.vely < 0)
Sprite_Animate(pacman.frame, pacman.startframe, 18, 4, pacman.starttime, 250);
else if (pacman.vely > 0)
Sprite_Animate(pacman.frame, pacman.startframe, 16, 2, pacman.starttime, 250);
else if (pacman.velx < 0)
Sprite_Animate(pacman.frame, pacman.startframe, 17, 3, pacman.starttime, 250);
else if (pacman.velx > 0)
Sprite_Animate(pacman.frame, pacman.startframe, 15, 1, pacman.starttime, 250);
pacman.y += pacman.vely;
pacman.x += pacman.velx;
}
trust that I've defined everything that is not pasted and linked headers correctly. Any ideas where I'm going wrong?
You're only checking for collisions in one case:
//check North collision
if (direction == 1 && N_tilevalue != 0)
{
return IntersectRect(&dest, &spriteRect, &northRect);
}
else return false; // <--- this
//check South collision
if (direction == 2 && S_tilevalue != 0)
{
return IntersectRect(&dest, &spriteRect, &southRect);
}
else return false; // <--- and this, etc...
See the line highlighted above. If it doesn't test for a North collision (i.e. if direction isn't 1 or N_tilevalue is 0) then the function returns at that point in all other cases. It can never go on to do the other collision checks.

Sprite can not move in cocos2d-x

I am new on cocos2d-x, i followed Cocos2d-x Game Development Essentials Ebook and trying to make demo app in iOS. with the help of its guidance,but when i trying to Move Astroids in GameScreen.cpp file as written in book, they actually doesn't move and i can't understand what am i missing?
here is code that i used:
bool GameScene::init()
{
//////////////////////////////
// 1. super init first
if ( !Layer::init() )
{
return false;
}
//Add EVENT LISTENER TO HANDLE TOUCH EVENT,
auto listener = EventListenerTouchOneByOne::create();
listener->setSwallowTouches(true);
listener->onTouchBegan = CC_CALLBACK_2(GameScene::ontouchBegin,this);
listener->onTouchMoved = CC_CALLBACK_2(GameScene::ontouchMoved, this);
listener->onTouchCancelled = CC_CALLBACK_2(GameScene::ontouchCanceled, this);
listener->onTouchEnded = CC_CALLBACK_2(GameScene::ontouchEnded, this);
this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);
istouching = false;
touchPosition = 0;
visibleSize = Director::getInstance()->getVisibleSize();
origin = Director::getInstance()->getVisibleOrigin();
auto backgroundSprite = Sprite::create("Game_Screen_Background.png");
backgroundSprite->setPosition(Point((visibleSize.width/2)+origin.x,(visibleSize.height/2)+origin.y));
this->addChild(backgroundSprite, -1);
auto pauseItem =
MenuItemImage::create("Pause_Button.png","Pause_Button(Click).png",CC_CALLBACK_1(GameScene::PushToGamePauseScene, this));
pauseItem->setPosition(Point(pauseItem->getContentSize().width-(pauseItem->getContentSize().width/4)+origin.x,visibleSize.height - pauseItem->getContentSize().height +(pauseItem->getContentSize().width / 4) + origin.y));
auto menu = Menu::create(pauseItem, NULL);
menu->setPosition(Point::ZERO);
this->addChild(menu);
for (int i = 0; i < 2; i ++){
backgroundSpriteArray[i] = Sprite::create("Game_Screen_Background.png");
backgroundSpriteArray[i]->setPosition(Point((visibleSize.width/2)+origin.x,(-1*visibleSize.height*i)+(visibleSize.height/2)+origin.y));
this->addChild(backgroundSpriteArray[i],-2);
}
playerSprite = Sprite::create("Space_Pod.png");
playerSprite->setPosition(Point(visibleSize.width/2,pauseItem->getPosition().y-(pauseItem->getContentSize().height/2)-(playerSprite->getContentSize().height/2)));
this->addChild(playerSprite, 1);
this->schedule(schedule_selector(GameScene::spawnAsteroid), 1.0);
this->scheduleUpdate();
return true;
}
Following is update method
void GameScene::update(float dt){
Size visibleSize = Director::getInstance()->getVisibleSize();
Point origin = Director::getInstance()->getVisibleOrigin();
for (int i = 0; i < 2; i ++){
if (backgroundSpriteArray[i]->getPosition().y >=visibleSize.height + (visibleSize.height / 2) -1){
backgroundSpriteArray[i]->setPosition(Point((visibleSize.width / 2) + origin.x, (-1 *visibleSize.height) + (visibleSize.height / 2)));
}
}
for (int i = 0; i < 2; i ++){
backgroundSpriteArray[i]->setPosition(Point(backgroundSpriteArray[i]->getPosition().x,backgroundSpriteArray[i]->getPosition().y + (0.75 *visibleSize.height * dt)));
}
for (int i = 0; i < asteroids.size(); i++){
asteroids[i]->setPosition(Point(asteroids[i]->getPosition().x,asteroids[i]->getPosition().y+(0.75 * visibleSize.height * dt)));
if (asteroids[i]->getPosition().y > visibleSize.height * 2){
this->removeChild(asteroids[i]);
asteroids.erase(asteroids.begin() + i);
}
}
//check for Touching
if(istouching == true){
//now check, which side of the screen is being touched
if(touchPosition < visibleSize.width /2){
//now, move the space pod to left
float positionX = playerSprite->getPosition().x;
playerSprite->setPositionX(positionX - (0.50* visibleSize.width * dt));
positionX = playerSprite->getPositionX();
//prevent space pod to getting off the screen (left side)
if(positionX <= 0+(playerSprite->getContentSize().width/2))
{
playerSprite->setPositionX(playerSprite->getContentSize().width / 2);
}
}
else{
//now, move the space pod to right
float positionX = playerSprite->getPositionX();
playerSprite->setPositionX(positionX + (0.50 * visibleSize.width *dt));
positionX = playerSprite->getPositionX();
// check to prevent the space pod from going off the screen (right side)
if(positionX >= visibleSize.width-(playerSprite->getContentSize().width/2))
{
playerSprite->setPositionX(visibleSize.width-(playerSprite->getContentSize().width/2));
}
}
}
}
For move astroid code:
void GameScene::spawnAsteroid(float dt){
Size visibleSize = Director::getInstance()->getVisibleSize();
Point origin = Director::getInstance()->getVisibleOrigin();
int asteroidIndex = (arc4random() % 3) + 1;
__String* asteroidString = __String::createWithFormat("Asteroid_%i.png",asteroidIndex);
auto *tempAsteroid = Sprite::create(asteroidString->getCString());
int xRandomPosition = (arc4random() % (int)(visibleSize.width - (tempAsteroid->getContentSize().width / 2))) + (tempAsteroid->getContentSize().width / 2);
tempAsteroid->setPosition(Point(xRandomPosition + origin.x, -tempAsteroid->getContentSize().height +origin.y));
asteroids.push_back(tempAsteroid);
this->update(touchPosition);
this->addChild(asteroids[asteroids.size() - 1], -1);
}
That method has been called at run time but don't know that my astroid object does not moved can anybody please help me for figure it out issue and how to fix it.
Edit
OK,i put this->scheduleUpdate() in init(),and starts moving astroids on the screen but when i move my sprite(not astroids) with touchBegin event the astroid got disappear from screen. please guide me on this.
please put this line in your init method
this->scheduleUpdate();
Hope it helps
Sprite->runAction(Sequence::create(MoveTo::create(1.0f, Vec2(100,200)),NULL));