Cross-posted from Slembcke forums:
I've been learning cocos and chipmunk together, seen all the various tutorials and tried to piece together how to build a side-scrolling shooter, but the physics involved is tripping me up. I really scoured the forums here and at the cocos2d forums for relevant tidbits, however I am just going to ask here since after all that I am still confused. Hope y'all don't mind one more projectiles question (and subsequent follow-ups!). :)
I have a Hero firing Arrows at Monsters. When I touch the screen, I want the Hero to fire an Arrow from where he is, to where the touch occurred. Therefore, the aim will take different angles...I reached into my Trigonometry bag and pulled out equations to calculate the angle needed to fire the Arrow at to hit the point I touched. Then I realized that there are some functions in chipmunk (cpvforangle?) that probably do this already? So, that's the first question: What is the easiest / best way to determine angle from one point to another point?
Moving forward, I plugged in some hard-coded values to test if my Shape and Sprite fire in a different direction. It does weird things like slowly eject the arrows (whose Sprites are slightly rotated now...) from the Hero and send them in a straight line. Here is that code:
- (void) fireFrom:(cpVect)from to:(cpVect)to {
float adj = to.x - from.x;
float opp = to.y - from.y;
float hyp = sqrt( (adj * adj) + (opp * opp) );
DebugLog(@"triangle - adjacent: %f opposite: %f hypotneuse: %f", adj, opp, hyp);
float radians = acos(adj / hyp);
shape->body->p = from;
shape->body->v = cpv(500, 100);
cpBodySetAngle(shape->body, radians);
cpBodyApplyImpulse(shape->body, cpv(200,100), to);
[self setRotation:45];
}
Here is the initialization code for the Arrow (which subclasses Projectile, which subclasses Sprite):
- (id) initWithFile:(NSString *)filename {
self = [super initWithFile:filename];
if(self != nil) {
cpVect verts[] = { cpv(-3,-1), cpv(-3, 1), cpv(3, 1), cpv(3,-1),};
//cpBody *body = cpBodyNew(10.0f, cpMomentForPoly(10.0f, 4, verts, cpv(1,1)));
// NOT SURE WHAT TO PUT AS SECOND ARGUMENT (INERTIA)
cpBody *body = cpBodyNew(10.0f, INFINITY);
body->data = self;
shape = cpPolyShapeNew(body, 4, verts, cpvzero);
shape->e = 0.0f;
shape->u = 1.0f;
shape->data = self;
shape->collision_type = ARROW_COLLISION_TYPE;
[self setPosition:cpv(-50, -50)];
ready = YES;
}
return self;
}
I subclass Projectile so I can share the following methods with all my potential ammunition (fireballs, lightning, multi-shot):
- (void) resetPosition {
[self setPosition:cpv(-50, -50)];
}
- (void) setPosition:(cpVect)newPosition {
[super setPosition:newPosition];
shape->body->p = newPosition;
}
- (void) setRotation:(float)newRotation {
[super setRotation:newRotation];
cpBodySetAngle(shape->body, CC_DEGREES_TO_RADIANS(-newRotation));
}
Huge thanks in advance to anyone who can guide me through what I am misunderstanding. I think I am close, I just need to understand the higher level concepts more. Also let me know if you need more code to figure this out...I'm happy to share whatever.