Cocos2dx Inherited CCNode class not rotating around around its center? - rotation

I'm at a bit of a loss here, forgive me if this has already been asked - i've have searched google high and low but i cant find anything?
i'm trying to rotate a group of sprites that are generated in a class, then rotating this object in the main gamescene on a menuitem click but the rotation is not at the center of the sprite? it a some larger area probably the layer size?
I've tried setting the anchorpoint to every possible combination?
Here is what iv got
This is the gamecharacter.h
#define COMPUTE_X(x) ((abs(x)) * 16) + (16*2) + (16/2)
#define COMPUTE_Y(y) (386 - (abs(y) * 16)) + (16/2)
#define COMPUTE_X_Y(x,y) ccp( COMPUTE_X(x), COMPUTE_Y(y))
// Game character class
#include "cocos2d.h"
using namespace cocos2d;
//a class to encapsulate playable game character by creating a group of sprites etc..
#ifndef GAMECHARACTER_H
#define GAMECHARACTER_H
class GameCharacter : public CCNode {
private:
//some private methods etc....
public:
void addSprite(const char* filename);
void setInitialPosition(CCPoint* position);
//Various other methods.........
};
#endif
void GameCharacter::addSprite(const char* filename)
{
//go get the sprite sheet
CCTexture2D* gameArtTexture = CCTextureCache::sharedTextureCache()->addPVRImage("SpriteSheet.pvr.ccz");
CCSpriteBatchNode::batchNodeWithTexture(gameArtTexture);
CCSprite *tempBlock = CCSprite::spriteWithSpriteFrameName(filename);
this->addChild((CCSprite*)tempBlock,0);
}
void GameCharacter::setInitialPosition(CCPoint* position)
{
//loop through the positions and set the character up
CCArray *children = this->getChildren();
CCSprite *currentBlock;
for (int i=0;i<7;i++){
currentBlock = (CCSprite*) children->objectAtIndex(i);
//compute x y grid positions (1,1) ---> to real (72,394)
currentBlock->setPosition(COMPUTE_X_Y(position[i].x,position[i].y));
}
}
This is the gamecharacter.cpp
void GameScene::AddCharacter(CCPoint* position)
{
const char* filename;
GameCharacter* character = new GameCharacter();
for (int i = 0; i < 7; i++) {
filename = helperFunctions::Format("character%d.png",i+1); //character1.png -> character7.png
character->addSprite(filename);
}
character->setInitialPosition(position);
this->addChild((CCSprite*) character,-1,2);
_sprite = character;
}
//here is the menuitem click handler
void GameScene::menuRotateRightCallback(CCObject* pSender)
{
//rotate the character right
//really slowly so we can see whats happening
_sprite->runAction((CCRotateBy::actionWithDuration(2.50,90)));
}
Thanks

It is much easier to do, using
x = center.x + cos(angle) * radius;
y = center.y + sin(angle) * radius;

Ive figured it out, looking at the docs for CCNode made me think.
CCNode has a position of (0,0) by default, so the rotation was using this as an origin.
Setting the position to the center of where i want the character with a bit of maths to calculate the offsets works for me.

Related

How to hide invisible elements of the 3d drawing?

I'm trying to draw a 3d image that displays a ripple:
function myFunc(x, y) {
let zRipple =
Math.pow(2, -0.005 * (Math.abs(x) + Math.abs(y))) *
Math.cos(((x * x + y * y) * 2 * pi) / 180 / width) *
height;
return zRipple;
}
width and height here are constants that define a drawing area and are equal to 200 in my tests.
My approach is based on what I recall from an article that I read 30 years ago and trying to recall now.
The idea is to:
split the whole drawing board into the 10-pixel grid
for each 'cell' of the grid, draw a line to the nearest cell along the Y- and the X-axis' (step=10, ds=0.0
for (let x3 = width; x3 >= - width; x3 -= step) {
for (let y3 = -height; y3 <= height; y3 += step) {
for (let s = 0; s < step; s += ds) {
let x = x3 + s;
if (x < width) {
let z3 = myFunc(x, y3);
drawPixel3d(x, y3, z3);
}
}
for (let s = 0; s < step; s += ds) {
let y = y3 + s;
if (y < height) {
let z3 = myFunc(x3, y);
drawPixel3d(x3, y, z3);
}
}
}
}
}
Here is how I convert 3d coordinates to 2d:
function drawPixel3d(x3, y3, z3) {
let x2 = (x3 + y3) * Math.sin((60 * pi) / 180);
let y2 = z3 - ((x3 - y3) * Math.sin((30 * pi) / 180)) / 4;
drawPixel(x2, y2);
}
As you see from the image below, I get a decent graphic, but there is a problem: I draw ALL dots, not only those, that are VISIBLE.
Question: How do I check if any pixel needs to be displayed or not?
From what I can recall in that article, we should follow the approach:
start drawing from the front part of the scene (which I believe I do, the closest to the viewer or screen if dot with coordinates (width, -height)
for each pixel column - remember the 'Z' coordinate and only draw the new pixel if its Z-coordinate is bigger than the last recorded one
To achieve this I've modified my 'drawPixel3d' method:
function drawPixel3d(x3, y3, z3) {
let x2 = (x3 + y3) * Math.sin((60 * pi) / 180);
let y2 = z3 - ((x3 - y3) * Math.sin((30 * pi) / 180)) / 4;
let n = Math.round(x2);
let visible = false;
if (zs[n] === undefined) {
zs[n] = z3;
visible = true;
} else {
if (z3 > zs[n]) {
visible = z3 > zs[n];
zs[n] = z3;
}
}
if (visible) drawPixel(x2, y2);
}
But the result is not expected:
What do I do wrong? Or an alternative question: how to draw a simple 3d graphic?
Thanks!
P.S. The last piece of the program (that illustrates inversion of Y-coordinate during actual drawing):
function drawPixel(x: number, y: number) {
ctx.fillRect(cX + x, cY - y, 1, 1); // TS-way to draw pixel on canvas is to draw a rectangle
} // cX and cY are coordinates of the center of the drawing canvas
P.P.S. I have an idea of the algorithmic solution, so added an 'algorithm' tag: maybe someone from this community can help?
Your surface is concave which means you can not use simple methods based on dot product between face normal and camera view direction.
You got 3 obvious options for this.
use ray tracing
as you got analytical equation of the surface this might be even better way
use depth buffering to mask out the invisible stuff
As you render wireframe then you need to do this in 2 passes:
render invisible filled surface (fill just depth buffer not the screen)
render wireframe
your depth buffer condition must contain also equal values so either z<=depth[y][x] or z>=depth[y][x]
However you need to use face rendering (triangles or quads ...) and I assume this is software rendering so if you not familiar on such stuff see:
how to rasterize rotated rectangle (in 2d by setpixel)
Algorithm to fill triangle
use depth sorting by exploiting topology
If you do not have view transform so your x,y,z coordinates are directly corresponding to camera space coordinates then you can render the grid in back to front order simply by ordering the for loops and direction of iteration (its common in isometric views). This does not need depth buffering however you need to render filled QUADS in order to obtain correct output (border is set to the plot color and the inside is filled with background color).
I did go for the #2 approach. When I ported the last link into 3D I got this (C++ code):
//---------------------------------------------------------------------------
const int col_transparent=-1; // transparent color
class gfx_main
{
public:
Graphics::TBitmap *bmp; // VCL bitmap for win32 rendering
int **scr,**zed,xs,ys; // screen,depth buffers and resolution
struct pbuf // convex polygon rasterization line buffer
{
int x,z; // values to interpolate during rendering
pbuf() {}
pbuf(pbuf& a) { *this=a; }
~pbuf() {}
pbuf* operator = (const pbuf *a) { *this=*a; return this; }
//pbuf* operator = (const pbuf &a) { ...copy... return this; }
} *pl,*pr; // left,right buffers
gfx_main();
gfx_main(gfx_main& a) { *this=a; }
~gfx_main();
gfx_main* operator = (const gfx_main *a) { *this=*a; return this; }
//gfx_main* operator = (const gfx_main &a) { ...copy... return this; }
void resize(int _xs=-1,int _ys=-1);
void clear(int z,int col); // clear buffers
void pixel(int x,int y,int z,int col); // render 3D point
void line(int x0,int y0,int z0,int x1,int y1,int z1,int col); // render 3D line
void triangle(int x0,int y0,int z0,int x1,int y1,int z1,int x2,int y2,int z2,int col); // render 3D triangle
void _triangle_line(int x0,int y0,int z0,int x1,int y1,int z1); // this is just subroutine
};
//---------------------------------------------------------------------------
gfx_main::gfx_main()
{
bmp=new Graphics::TBitmap;
scr=NULL;
zed=NULL;
pl =NULL;
pr =NULL;
xs=0; ys=0;
resize(1,1);
}
//---------------------------------------------------------------------------
gfx_main::~gfx_main()
{
if (bmp) delete bmp;
if (scr) delete[] scr;
if (zed)
{
if (zed[0]) delete[] zed[0];
delete[] zed;
}
if (pl) delete[] pl;
if (pr) delete[] pr;
}
//---------------------------------------------------------------------------
void gfx_main::resize(int _xs,int _ys)
{
// release buffers
if (scr) delete[] scr;
if (zed)
{
if (zed[0]) delete[] zed[0];
delete[] zed;
}
if (pl) delete[] pl;
if (pr) delete[] pr;
// set new resolution and pixelformat
if ((_xs>0)&&(_ys>0)) bmp->SetSize(_xs,_ys);
xs=bmp->Width;
ys=bmp->Height;
bmp->HandleType=bmDIB;
bmp->PixelFormat=pf32bit;
// allocate buffers
scr=new int*[ys];
zed=new int*[ys];
zed[0]=new int[xs*ys]; // allocate depth buffer as single block
for (int y=0;y<ys;y++)
{
scr[y]=(int*)bmp->ScanLine[y]; // screen buffer point directly to VCL bitmap (back buffer)
zed[y]=zed[0]+(y*xs); // just set pointers for each depth line instead of allocating it
}
pl=new pbuf[ys];
pr=new pbuf[ys];
}
//---------------------------------------------------------------------------
int rgb2bgr(int col) // just support function reversing RGB order as VCL/GDI and its direct pixel access are not the same pixelformat
{
union
{
BYTE db[4];
int dd;
} c;
BYTE q;
c.dd=col;
q=c.db[0]; c.db[0]=c.db[2]; c.db[2]=q;
return c.dd;
}
//---------------------------------------------------------------------------
void gfx_main::clear(int z,int col)
{
// clear buffers
int x,y;
col=rgb2bgr(col);
for (y=0;y<ys;y++)
for (x=0;x<xs;x++)
{
scr[y][x]= 0x00000000; // black
zed[y][x]=-0x7FFFFFFF; // as far as posible
}
}
//---------------------------------------------------------------------------
void gfx_main::pixel(int x,int y,int z,int col)
{
col=rgb2bgr(col);
if ((x>=0)&&(x<xs)&&(y>=0)&&(y<ys)) // inside screen
if (zed[y][x]<=z) // not after something already rendered (GL_LEQUAL)
{
zed[y][x]=z; // update depth
if (col!=col_transparent) scr[y][x]=col;// update color
}
}
//---------------------------------------------------------------------------
void gfx_main::line(int x0,int y0,int z0,int x1,int y1,int z1,int col)
{
int i,n,x,y,z,kx,ky,kz,dx,dy,dz,cx,cy,cz;
// DDA variables (d)abs delta,(k)step direction
kx=0; dx=x1-x0; if (dx>0) kx=+1; if (dx<0) { kx=-1; dx=-dx; }
ky=0; dy=y1-y0; if (dy>0) ky=+1; if (dy<0) { ky=-1; dy=-dy; }
kz=0; dz=z1-z0; if (dz>0) kz=+1; if (dz<0) { kz=-1; dz=-dz; }
n=dx; if (n<dy) n=dy; if (n<dz) n=dz; if (!n) n=1;
// integer DDA
for (x=x0,y=y0,z=z0,cx=cy=cz=n,i=0;i<n;i++)
{
pixel(x,y,z,col);
cx-=dx; if (cx<=0){ cx+=n; x+=kx; }
cy-=dy; if (cy<=0){ cy+=n; y+=ky; }
cz-=dz; if (cz<=0){ cz+=n; z+=kz; }
}
}
//---------------------------------------------------------------------------
void gfx_main::triangle(int x0,int y0,int z0,int x1,int y1,int z1,int x2,int y2,int z2,int col)
{
int x,xx0,xx1,y,yy0,yy1,z,zz0,zz1,dz,dx,kz,cz;
// boundary line coordinates to buffers
_triangle_line(x0,y0,z0,x1,y1,z1);
_triangle_line(x1,y1,z1,x2,y2,z2);
_triangle_line(x2,y2,z2,x0,y0,z0);
// y range
yy0=y0; if (yy0>y1) yy0=y1; if (yy0>y2) yy0=y2;
yy1=y0; if (yy1<y1) yy1=y1; if (yy1<y2) yy1=y2;
// fill with horizontal lines
for (y=yy0;y<=yy1;y++)
if ((y>=0)&&(y<ys))
{
if (pl[y].x<pr[y].x){ xx0=pl[y].x; zz0=pl[y].z; xx1=pr[y].x; zz1=pr[y].z; }
else { xx1=pl[y].x; zz1=pl[y].z; xx0=pr[y].x; zz0=pr[y].z; }
dx=xx1-xx0;
kz=0; dz=zz1-zz0; if (dz>0) kz=+1; if (dz<0) { kz=-1; dz=-dz; }
for (cz=dx,x=xx0,z=zz0;x<=xx1;x++)
{
pixel(x,y,z,col);
cz-=dz; if (cz<=0){ cz+=dx; z+=kz; }
}
}
}
//---------------------------------------------------------------------------
void gfx_main::_triangle_line(int x0,int y0,int z0,int x1,int y1,int z1)
{
pbuf *pp;
int i,n,x,y,z,kx,ky,kz,dx,dy,dz,cx,cy,cz;
// DDA variables (d)abs delta,(k)step direction
kx=0; dx=x1-x0; if (dx>0) kx=+1; if (dx<0) { kx=-1; dx=-dx; }
ky=0; dy=y1-y0; if (dy>0) ky=+1; if (dy<0) { ky=-1; dy=-dy; }
kz=0; dz=z1-z0; if (dz>0) kz=+1; if (dz<0) { kz=-1; dz=-dz; }
n=dx; if (n<dy) n=dy; if (n<dz) n=dz; if (!n) n=1;
// target buffer according to ky direction
if (ky>0) pp=pl; else pp=pr;
// integer DDA line start point
x=x0; y=y0;
// fix endpoints just to be sure (wrong division constants by +/-1 can cause that last point is missing)
if ((y0>=0)&&(y0<ys)){ pp[y0].x=x0; pp[y0].z=z0; }
if ((y1>=0)&&(y1<ys)){ pp[y1].x=x1; pp[y1].z=z1; }
// integer DDA (into pbuf)
for (x=x0,y=y0,z=z0,cx=cy=cz=n,i=0;i<n;i++)
{
if ((y>=0)&&(y<ys))
{
pp[y].x=x;
pp[y].z=z;
}
cx-=dx; if (cx<=0){ cx+=n; x+=kx; }
cy-=dy; if (cy<=0){ cy+=n; y+=ky; }
cz-=dz; if (cz<=0){ cz+=n; z+=kz; }
}
}
//---------------------------------------------------------------------------
Just ignore/port the VCL stuff. I just added z coordinate to interpolation and rendering and also depth buffer. The rendering code looks like this:
//---------------------------------------------------------------------------
gfx_main gfx;
//---------------------------------------------------------------------------
float myFunc(float x,float y)
{
float z;
x-=gfx.xs/2;
y-=gfx.ys/2;
z=sqrt(((x*x)+(y*y))/((gfx.xs*gfx.xs)+(gfx.ys*gfx.ys))); // normalized distance from center
z=((0.25*cos(z*8.0*M_PI)*(1.0-z))+0.5)*gfx.ys;
return z;
}
//---------------------------------------------------------------------------
void view3d(int &x,int &y,int &z) // 3D -> 2D view (projection)
{
int zz=z;
z=y;
x=x +(y/2)-(gfx.xs>>2);
y=zz+(y/2)-(gfx.ys>>2);
}
//---------------------------------------------------------------------------
void draw()
{
int i,x,y,z,ds,x0,y0,z0,x1,y1,z1,x2,y2,z2,x3,y3,z3,col;
gfx.clear(-0x7FFFFFFF,0x00000000);
// render
ds=gfx.xs/50;
for (i=0;i<2;i++) // 2 passes
for (y=ds;y<gfx.ys;y+=ds)
for (x=ds;x<gfx.xs;x+=ds)
{
// 4 vertexes of a quad face
x0=x-ds; y0=y-ds; z0=myFunc(x0,y0);
x1=x; y1=y0; z1=myFunc(x1,y1);
x2=x; y2=y; z2=myFunc(x2,y2);
x3=x0; y3=y; z3=myFunc(x3,y3);
// camera transform
view3d(x0,y0,z0);
view3d(x1,y1,z1);
view3d(x2,y2,z2);
view3d(x3,y3,z3);
if (i==0) // first pass
{
// render (just to depth)
col=col_transparent;
gfx.triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,col);
gfx.triangle(x0,y0,z0,x2,y2,z2,x3,y3,z3,col);
}
if (i==1) // second pass
{
// render wireframe
col=0x00FF0000;
gfx.line(x0,y0,z0,x1,y1,z1,col);
gfx.line(x1,y1,z1,x2,y2,z2,col);
gfx.line(x2,y2,z2,x3,y3,z3,col);
gfx.line(x3,y3,z3,x0,y0,z0,col);
}
}
// here gfx.scr holds your rendered image
//---------------------------------------------------------------------------
Do not forget to call gfx.resize(xs,ys) with resolution of your view before rendering. As you can see I used different function (does not matter) here the output:
And here the same without depth condition in pixel(x,y,z,col)
The pbuf structure holds all the stuff that will be interpolated in the last rendering interpolation of the horizontal lines. So if you want gourard, textures or whatever you just add the variable to this structure and add the interpolation to the code (mimic the pbuf[].z interpolation code)
However this approach has one drawback. Your current approach interpolates one axis pixel by pixel and the other is stepping by grid size. This one is stepping both axises by grid size. So if you want to have the same behavior you might to do the first pass with 1 x 1 quads instead of ds x ds and then do the lines as you do now. In case 1 in your view is corresponding to pixel then you can do this on pixels alone without the face rendering however you risk holes in the output.
I got the idea of the solution: start drawing from the point nearest to the observer but for every combination of x2 and y2 coordinates draw the pixel only once and only when it is visible (never draw points behind others)... The only problem is that I don't draw EVERY point of the surface, I only draw a surface grid with 10 points step. As a result, part of the surface will be visible in 'between' the grid cells.
Another idea is to calculate distance from every drawing point of the surface to the observer and make sure to draw only that point that is visible of the surface that is CLOSEST to the observer... but how?

Sierpinski carpet in processing

So I made the Sierpinski carpet fractal in processing using a Square data type which draw a square and has a function generate() that generates 9 equal squares out of itself and returns an ArrayList of (9-1)=8 squares removing the middle one (it is not added to the returned ArrayList) in order to generate the Sierpinski carpet.
Here is the class Square -
class Square {
PVector pos;
float r;
Square(float x, float y, float r) {
pos = new PVector(x, y);
this.r = r;
}
void display() {
noStroke();
fill(120,80,220);
rect(pos.x, pos.y, r, r);
}
ArrayList<Square> generate() {
ArrayList<Square> rects = new ArrayList<Square>();
float newR = r/3;
for (int i=0; i<3; i++) {
for (int j=0; j<3; j++) {
if (!(i==1 && j==1)) {
Square sq = new Square(pos.x+i*newR, pos.y+j*newR, newR);
rects.add(sq);
}
}
}
return rects;
}
}
This is the main sketch which moves forward the generation on mouse click -
ArrayList<Square> current;
void setup() {
size(600, 600);
current = new ArrayList<Square>();
current.add(new Square(0, 0, width));
}
void draw() {
background(255);
for (Square sq : current) {
sq.display();
}
}
void mousePressed() {
ArrayList<Square> next = new ArrayList<Square>();
for(Square sq: current) {
ArrayList<Square> rects = sq.generate();
next.addAll(rects);
}
current = next;
}
The problem :
The output that I am getting has very thin white lines which are not supposed to be there :
First generation -
Second generation -
Third generation -
My guess is that these lines are just the white background that shows up due to the calculations in generate() being off by a pixel or two. However I am not sure about how to get rid of these. Any help would be appreciated!
Here's a smaller example that demonstrates your problem:
size(1000, 100);
noStroke();
background(0);
float squareWidth = 9.9;
for(float squareX = 0; squareX < width; squareX += squareWidth){
rect(squareX, 0, squareWidth, height);
}
Notice that the black background is showing through the squares. Please try to post this kind of minimal example instead of your whole sketch in the future.
Anyway, there are three ways to fix this:
Option 1: Call the noSmooth() function.
By default, Processing uses anti-aliasing to make your drawings look smoother. Usually this is a good thing, but it can also add some fuzziness to the edges of shapes. If you disable anti-aliasing, your shapes will be more clear and you won't see the artifacts.
Option 2: Use a stroke with the same color as the fill.
As you've already discovered, this draws an outline around the shape.
Option 3: Use int values instead of float values.
You're storing your coordinates and sizes in float values, which can contain decimal places. The problem is, the screen (the actual pixels on your monitor) don't have decimal places (there is no such thing as half a pixel), so they're represented by int values. So when you convert a float value to an int, the decimal part is dropped, which can cause small gaps in your shapes.
If you just switch to using int values, the problem goes away:
size(1000, 100);
noStroke();
background(0);
int squareWidth = 10;
for(int squareX = 0; squareX < width; squareX += squareWidth){
rect(squareX, 0, squareWidth, height);
}

2D Elastic Collision with SFML

I'm a complete beginner to OOP and I'm trying to figure out the best way to write a program for 2D collision of circles of equal mass in SFML C++. I want to generate two or more circles in a box with set starting velocity, but random starting position and direction, then have them interact. I'm having a lot of difficulty with the pseudocode for the mechanics since my physics is very rusty. I found this equation for 2D elastic collisions on wiki:
Does this mean that I should use this for both the x and y coordinates for each ball? I was thinking of doing something like this for the balls and velocities:
std::vector<sf::CircleShape> balls;
std::vector<sf::Vector2f> Xvelocities; // (magnitudes, directions)
std::vector<sf::Vector2f> Yvelocities; // (magnitudes, directions)
and I wrote a collision function like this:
bool Collision_Detection(sf::CircleShape &ball1, sf::CircleShape &ball2)
{
bool collision = false;
float distance = sqrt(pow(ball2.getPosition().x - ball1.getPosition().x, 2) +
pow(ball2.getPosition().y - ball1.getPosition().y, 2));
if (distance <= ball1.getRadius() + ball2.getRadius() + 4)
collision = true;
return collision;
The detection sometimes works and sometimes gets stuck, I'm not sure if it's a problem with the logic or if the performance is bad and I need to do bounding-box collision first.
Does how I'm going about this make any sense? Is there something I'm overlooking or a more standard way that people usually code this?
For rectangles there are sf::Rect<typename T> with the intersects()-method but nothing like sf::Circle<typename T> and such a method. This is because SFML needs a rectangle-class in for example the management of textures. The problem with no support for circles facing other SFML-developers too. So one of them created an SFML "extension" wich add a sf::Circle<typename T>
Here are his code:
namespace sf
{
template <typename T>
class Circle
{
public:
T x, y;
T radius;
Circle<T>()
{
this->x = T(0);
this->y = T(0);
this->radius = T(0);
}
Circle<T>(T _x, T _y, T _radius)
{
this->x = _x + _radius;
this->y = _y + _radius;
this->radius = _radius;
}
Circle<T>(sf::CircleShape cShape)
{
this->x = T(cShape.getRadius() + cShape.getPosition().x);
this->y = T(cShape.getRadius() + cShape.getPosition().y);
this->radius = T(cShape.getRadius());
}
bool intersects(sf::Circle<T> circle)
{
return (sqrt(pow(this->x - circle.x, 2) + pow(this->y - circle.y, 2)) >= this->radius + circle.radius)
}
bool contains(sf::Vector2<T> vecT)
{
return (sqrt(float(pow(float(this->x - vecT.x), (float)2) + pow(float(this->y - vecT.y), (float)2))) <= this->radius)
}
};
typedef sf::Circle<int> IntCircle;
typedef sf::Circle<double> DoubleCircle;
typedef sf::Circle<float> FloatCircle;
typedef sf::Circle<unsigned int> UintCircle;
}
You can use it exactly like the rectangles. The author also provided an example:
sf::CircleShape sfCircle(20);
sfCircle.setPosition(100, 100);
sf::FloatCircle myCircle(sfCircle);
// or:
// sf::FloatCircle myCircle(100, 100, 20);
// ---------------------------------------
// or:
// sf::FloatCircle myCircle;
// myCircle.radius = 20;
// myCircle.x = 100 + myCircle.radius;
// myCircle.y = 100 + myCircle.radius;
if (myCircle.contains((sf::Vector2f)sf::Mouse::getPosition(window)))
{
//Collision.
}
I hope this can help you a bit.

Processing - how to add a drag facility to the graphics

I am new to Processing so this question might be ...
I want to add drag and drop facility to the graphics I generate.
I found Processing - Mouse Functions which explains how to add dragging to a specific object yet I am looking for a general solution in which i dont have to add the dragging methods for each object i want to be able to drag around.
thanks
One option is to encapsulate the functionality into a class you can extend.
If your graphics extend such a class, then they also become "draggable".
Here's a minimal example where the graphics are simply boxes, but extending the "draggable behaviour":
int nb = 3;
Box[] boxes = new Box[nb];//a list of draggable graphics, currently empty
void setup(){
size(400,400);
for(int i = 0 ; i < nb; i++){
boxes[i] = new Box();//populate the list with actual objects
boxes[i].x = 10+110*i;//and setup their coordinates
boxes[i].y = 100;//and dimenensions
boxes[i].w = boxes[i].h = 100;
}
}
void draw(){
background(0);//clear
for(int i = 0 ; i < nb; i++){
boxes[i].update(mouseX,mouseY);//update the internal state(if it's over or not, calculate drag offset, etc.)
boxes[i].draw();//render each graphics element on screen
}
}
void mouseDragged(){//if the mouse is dragged
for(int i = 0 ; i < nb; i++){//for each graphics element
if(boxes[i].isOver) {//if it's over
boxes[i].x = mouseX-boxes[i].offx;//than drag based on the mouse position
boxes[i].y = mouseY-boxes[i].offy;//but take te mouse offset in relation to each object into account
}
}
}
class Draggable{//a generic draggable template with no graphics to display
float x,y,w,h,offx,offy;//position, dimensions and x,y offset to drag
boolean isOver;//is the cursor over the bounding box of this object ?
void update(int mx,int my){//let's work that out based on the mouse x and y coordinates
isOver = ((mx >= x && mx <= x+w) && (my >= y && my <= y+h));//if it's within bounds on x and y axis, then we're in the over state
if(isOver){//if we're in the over state we can also update the mouse drag offsets
offx = mx-x;
offy = my-y;
}
}
}
class Box extends Draggable{
void draw(){
fill(isOver ? 127 : 255);
rect(x,y,w,h);
}
}
This would be a fun little opportunity to test an OOP concept: polymorphism
int nb = 6;
Draggable[] boxes = new Draggable[nb];//a list of draggable graphics, currently empty
void setup(){
size(400,400);
for(int i = 0 ; i < nb; i++){
boxes[i] = (random(1.0) > .5) ? new Box() : new Blob();//populate the list with actual objects
boxes[i].x = 10+110*i;//and setup their coordinates
boxes[i].y = 100;//and dimenensions
boxes[i].w = boxes[i].h = 100;
}
}
void draw(){
background(0);//clear
for(int i = 0 ; i < nb; i++){
boxes[i].update(mouseX,mouseY);//update the internal state(if it's over or not, calculate drag offset, etc.)
boxes[i].draw();//render each graphics element on screen
}
}
void mouseDragged(){//if the mouse is dragged
for(int i = 0 ; i < nb; i++){//for each graphics element
if(boxes[i].isOver) {//if it's over
boxes[i].x = mouseX-boxes[i].offx;//than drag based on the mouse position
boxes[i].y = mouseY-boxes[i].offy;//but take te mouse offset in relation to each object into account
}
}
}
class Draggable{//a generic draggable template with no graphics to display
float x,y,w,h,offx,offy;//position, dimensions and x,y offset to drag
boolean isOver;//is the cursor over the bounding box of this object ?
void update(int mx,int my){//let's work that out based on the mouse x and y coordinates
isOver = ((mx >= x && mx <= x+w) && (my >= y && my <= y+h));//if it's within bounds on x and y axis, then we're in the over state
if(isOver){//if we're in the over state we can also update the mouse drag offsets
offx = mx-x;
offy = my-y;
}
}
void draw(){}//empty implementation to be overwritten by a subclass
}
class Box extends Draggable{
void draw(){
fill(isOver ? 127 : 255);
rect(x,y,w,h);
}
}
class Blob extends Draggable{
void draw(){
fill(isOver ? 127 : 255);
ellipse(x,y,w,h);
}
}
This is an idea of how implement this, but there are multiple ways of achieving this.
Have a look at the Processing OOP tutorial or the more in depth Java OOP one
For example the above could be achieved using Interfaces or an AbstractClass.
It's up to your goals and restrictions what the best solution will be.

XNA Vector2 path contained inside rectangle

Hello I am new to XNA and trying to develop a game prototype where the character moves from one location to another using mouse clicks.
I have a Rectangle representing the current position. I get the target location as a Vector2 using player mouse input. I extract the direction vector from the source to the target by Vector2 subtraction.
//the cursor's coordinates should be the center of the target position
float x = mouseState.X - this.position.Width / 2;
float y = mouseState.Y - this.position.Height / 2;
Vector2 targetVector = new Vector2(x, y);
Vector2 dir = (targetVector - this.Center); //vector from source center to target
//center
I represent the world using a tile map, every cell is 32x32 pixels.
int tileMap[,];
What I want to do is check whether the direction vector above passes through any blue tiles on the map. A blue tile is equal 1 on the map.
I am not sure how to do this. I thought about using linear line equation and trigonometric formulas but I'm finding it hard to implement. I've tried normalizing the vector and multiplying by 32 to get 32 pixel length intervals along the path of the vector but it doesn't seem to work. Can anyone tell me if there's anything wrong in it, or another way to solve this problem? Thanks
//collision with blue wall. Returns point of impact
private bool CheckCollisionWithBlue(Vector2 dir)
{
int num = Worldmap.size; //32
int i = 0;
int intervals = (int)(dir.Length() / num + 1); //the number of 32-pixel length
//inervals on the vector, with an edge
Vector2 unit = Vector2.Normalize(dir) * num; //a vector of length 32 in the same
//direction as dir.
Vector2 v = unit;
while (i <= intervals & false)
{
int x = (int)(v.X / num);
int y = (int)(v.Y / num);
int type = Worldmap.getType(y, x);
if (type == 1) //blue tile
{
return true;
}
else
{
i++;
v = unit * i;
}
}
return false;
}
You need the initial postion too, not only direction
Maybe you need more resolution
¿what? remove the "false" evaluation
The calcs for next pos are a bit complicated
private bool CheckCollisionWithBlue(Vector2 source, Vector2 dir)
{
int num = 8; // pixel blocks of 8
int i = 0;
int intervals = (int)(dir.Length() / num);
Vector2 step = Vector2.Normalize(dir)*num;
while (i <= intervals)
{
int x = (int)(source.X);
int y = (int)(source.Y);
int type = Worldmap.getType(y, x);
if (type == 1) //blue tile
{
return true;
}
else
{
i++;
source+=step;
}
}
return false;
}
This will improve something your code, but maybe innacurate... it depends on what are you trying to do...
You maybe can find interesting the bresenham's line algorithm http://en.wikipedia.org/wiki/Bresenham's_line_algorithm
You should realize that you are not doing a volume collision but a line collision, if the ship or character or whatever that is at source position maybe you have to add more calcs

Resources