int PhysBody::RayCast(int x1, int y1, int x2, int y2, float& normal_x, float& normal_y) const { int ret = -1; bool hit = true; b2RayCastInput input; b2RayCastOutput output; b2Transform transform = body->GetTransform(); int32 childIndex = 0; b2Vec2 normalVec; float maxFraction = 1.0f; input.p1.Set(PIXEL_TO_METERS(x1), PIXEL_TO_METERS(y1)); input.p2.Set(PIXEL_TO_METERS(x2), PIXEL_TO_METERS(y2)); input.maxFraction = maxFraction; for (b2Fixture* f = body->GetFixtureList(); f; f = f->GetNext()) { transform = body->GetTransform(); hit = f->GetShape()->RayCast(&output, input, transform, childIndex); if (hit == true) { b2Vec2 dis = output.fraction * (input.p2 - input.p1); ret = METERS_TO_PIXELS(dis.Length()); normal_x = output.normal.x; normal_y = output.normal.y; } } return ret; /*TODO 2 “Write code to test a ray cast between both points provided. If not hit return -1. If hit, fill normal_x and normal_y and return the distance between x1, y1 and it's colliding point”*/ }
int PhysBody::RayCast(int x1, int y1, int x2, int y2, float& normal_x, float& normal_y) const { // TODO 2: Write code to test a ray cast between both points provided. If not hit return -1 // if hit, fill normal_x and normal_y and return the distance between x1,y1 and it's colliding point int hit = -1; int distance = -1; b2Vec2 p1(PIXEL_TO_METERS(x1), PIXEL_TO_METERS(y1)); b2Vec2 p2(PIXEL_TO_METERS(x2), PIXEL_TO_METERS(y2)); b2Vec2 normal(normal_x, normal_y); float maxFraction = 1.0f; b2RayCastInput input = { p1, p2, maxFraction }; b2RayCastOutput output; b2Fixture* f = body->GetFixtureList(); for (int i = 0; f; f = f->GetNext(), i++) { hit = f->GetShape()->RayCast(&output, input, body->GetTransform(), i); } if (hit) { b2Vec2 dis = input.p1 + output.fraction*(p2 - p1); distance = METERS_TO_PIXELS(dis.LengthSquared()); } //ask ric why we have to return an integer, because the distance won't be precise in pixels return distance; }
bool Player::update(float dt) { blitScore(); blitLifes(); iPoint pos(0, 0); //Ball ball->getPosition(pos.x, pos.y); app->render->blit(ball->texture, pos.x, pos.y, NULL, 1.0f, ball->getRotation()); if (!playing && !gameover) { app->render->blit(intro_tex, 0, 0); if (app->input->getMouseButton(SDL_BUTTON_LEFT) == KEY_DOWN) { app->input->getMousePosition(pos.x, pos.y); if (isInside(pos, play_button)) { playing = true; app->audio->playMusic("sounds/music/pinball_theme.ogg"); } } } if (!playing && gameover) { app->render->blit(gameover_tex, 0, 0); if (app->input->getMouseButton(SDL_BUTTON_LEFT) == KEY_DOWN) { app->input->getMousePosition(pos.x, pos.y); if (isInside(pos, replay_button)) { playing = true; gameover = false; app->audio->playMusic("sounds/music/pinball_theme.ogg"); } } } if (lifes == 0) { gameover = true; playing = false; lifes = 3; if (score > hi_score) hi_score = score; score = 0; app->audio->stopMusic(); app->audio->playFx(loser_sound); for (doubleNode<Sensor*> *sensor_item = app->scene->lights_sensors.getFirst(); sensor_item != NULL; sensor_item = sensor_item->next) sensor_item->data->collided = false; } if (playing) { static float push_force = 0.0f; if (app->input->getKey(SDL_SCANCODE_DOWN) == KEY_DOWN || app->input->getKey(SDL_SCANCODE_DOWN) == KEY_REPEAT) { push_force += 175.0f; app->scene->propulsor->push(0, push_force); } else if (app->input->getKey(SDL_SCANCODE_DOWN) == KEY_UP) { push_force = -500.0f; app->scene->propulsor->push(0, push_force); app->audio->playFx(launcher_sound); } else push_force = 0.0f; if (METERS_TO_PIXELS(ball->body->GetPosition().y) > 532) { ball->setLinearSpeed(0, 0); ball->setPosition(313, 450); lifes--; } if (app->input->getKey(SDL_SCANCODE_LEFT) == KEY_DOWN) { app->physics->activateLeftFlippers(); app->audio->playFx(flipper_sound); } if (app->input->getKey(SDL_SCANCODE_RIGHT) == KEY_DOWN) { app->physics->activateRightFlippers(); app->audio->playFx(flipper_sound); } if (app->input->getKey(SDL_SCANCODE_LEFT) == KEY_UP) app->physics->deactivateLeftFlippers(); if (app->input->getKey(SDL_SCANCODE_RIGHT) == KEY_UP) app->physics->deactivateRightFlippers(); } return true; }
void PhysBody::GetPosition(int& x, int &y) const { b2Vec2 pos = body->GetPosition(); x = METERS_TO_PIXELS(pos.x) - (width); y = METERS_TO_PIXELS(pos.y) - (height); }
update_status ModulePhysics::PostUpdate() { if(App->input->GetKey(SDL_SCANCODE_F1) == KEY_DOWN) debug = !debug; if (!debug){ return UPDATE_CONTINUE; } // Bonus code: this will iterate all objects in the world and draw the circles // You need to provide your own macro to translate meters to pixels for(b2Body* b = world->GetBodyList(); b; b = b->GetNext()) { for(b2Fixture* f = b->GetFixtureList(); f; f = f->GetNext()) { switch(f->GetType()) { // Draw circles ------------------------------------------------ case b2Shape::e_circle: { b2CircleShape* shape = (b2CircleShape*)f->GetShape(); b2Vec2 pos = f->GetBody()->GetPosition(); App->renderer->DrawCircle(METERS_TO_PIXELS(pos.x), METERS_TO_PIXELS(pos.y), METERS_TO_PIXELS(shape->m_radius), 255, 255, 255); } break; // Draw polygons ------------------------------------------------ case b2Shape::e_polygon: { b2PolygonShape* polygonShape = (b2PolygonShape*)f->GetShape(); int32 count = polygonShape->GetVertexCount(); b2Vec2 prev, v; for(int32 i = 0; i < count; ++i) { v = b->GetWorldPoint(polygonShape->GetVertex(i)); if(i > 0) App->renderer->DrawLine(METERS_TO_PIXELS(prev.x), METERS_TO_PIXELS(prev.y), METERS_TO_PIXELS(v.x), METERS_TO_PIXELS(v.y), 255, 100, 100); prev = v; } v = b->GetWorldPoint(polygonShape->GetVertex(0)); App->renderer->DrawLine(METERS_TO_PIXELS(prev.x), METERS_TO_PIXELS(prev.y), METERS_TO_PIXELS(v.x), METERS_TO_PIXELS(v.y), 255, 100, 100); } break; // Draw chains contour ------------------------------------------- case b2Shape::e_chain: { b2ChainShape* shape = (b2ChainShape*)f->GetShape(); b2Vec2 prev, v; for(int32 i = 0; i < shape->m_count; ++i) { v = b->GetWorldPoint(shape->m_vertices[i]); if(i > 0) App->renderer->DrawLine(METERS_TO_PIXELS(prev.x), METERS_TO_PIXELS(prev.y), METERS_TO_PIXELS(v.x), METERS_TO_PIXELS(v.y), 100, 255, 100); prev = v; } v = b->GetWorldPoint(shape->m_vertices[0]); App->renderer->DrawLine(METERS_TO_PIXELS(prev.x), METERS_TO_PIXELS(prev.y), METERS_TO_PIXELS(v.x), METERS_TO_PIXELS(v.y), 100, 255, 100); } break; // Draw a single segment(edge) ---------------------------------- case b2Shape::e_edge: { b2EdgeShape* shape = (b2EdgeShape*)f->GetShape(); b2Vec2 v1, v2; v1 = b->GetWorldPoint(shape->m_vertex0); v1 = b->GetWorldPoint(shape->m_vertex1); App->renderer->DrawLine(METERS_TO_PIXELS(v1.x), METERS_TO_PIXELS(v1.y), METERS_TO_PIXELS(v2.x), METERS_TO_PIXELS(v2.y), 100, 100, 255); } break; } // TODO 1: If mouse button 1 is pressed ... if (App->input->GetMouseButton(SDL_BUTTON_LEFT) == KEY_DOWN) { mouse_position.x = PIXEL_TO_METERS(App->input->GetMouseX()); mouse_position.y = PIXEL_TO_METERS(App->input->GetMouseY()); b2Vec2 point(mouse_position.x, mouse_position.y); // test if the current body contains mouse position if (f->TestPoint(point)) { body_clicked = f->GetBody(); LOG("HAS FET CLICK AL OBJECTE"); //break; } } } } // If a body was selected we will attach a mouse joint to it // so we can pull it around // TODO 2: If a body was selected, create a mouse joint // using mouse_joint class property if (body_clicked != NULL && App->input->GetMouseButton(SDL_BUTTON_LEFT) == KEY_DOWN) { mouse_position.x = PIXEL_TO_METERS(App->input->GetMouseX()); mouse_position.y = PIXEL_TO_METERS(App->input->GetMouseY()); b2MouseJointDef def; def.bodyA = ground; def.bodyB = body_clicked; def.target = mouse_position; def.dampingRatio = 0.5f; def.frequencyHz = 2.0f; def.maxForce = 100.0f * body_clicked->GetMass(); mouse_joint = (b2MouseJoint*)world->CreateJoint(&def); } // TODO 3: If the player keeps pressing the mouse button, update // target position and draw a red line between both anchor points if (body_clicked != NULL && App->input->GetMouseButton(SDL_BUTTON_LEFT) == KEY_REPEAT) { mouse_position.x = PIXEL_TO_METERS(App->input->GetMouseX()); mouse_position.y = PIXEL_TO_METERS(App->input->GetMouseY()); mouse_joint->SetTarget(mouse_position); App->renderer->DrawLine(mouse_position.x, mouse_position.y, body_clicked->GetPosition().x, body_clicked->GetPosition().y , 255, 0, 0, false); } // TODO 4: If the player releases the mouse button, destroy the joint //if (mouse_joint != NULL && App->input->GetMouseButton()) if (body_clicked != NULL && App->input->GetMouseButton(SDL_BUTTON_LEFT) == KEY_UP){ body_clicked = NULL; assert(mouse_joint); world->DestroyJoint(mouse_joint); } return UPDATE_CONTINUE; }
update_status ModulePhysics::PostUpdate() { // On space bar press, create a circle on mouse position if(App->input->GetKey(SDL_SCANCODE_F1) == KEY_DOWN) debug = !debug; if(!debug) return UPDATE_CONTINUE; // Bonus code: this will iterate all objects in the world and draw the circles // You need to provide your own macro to translate meters to pixels for(b2Body* b = world->GetBodyList(); b; b = b->GetNext()) { for(b2Fixture* f = b->GetFixtureList(); f; f = f->GetNext()) { switch(f->GetType()) { // Draw circles ------------------------------------------------ case b2Shape::e_circle: { b2CircleShape* shape = (b2CircleShape*)f->GetShape(); b2Vec2 pos = f->GetBody()->GetPosition(); App->renderer->DrawCircle(METERS_TO_PIXELS(pos.x), METERS_TO_PIXELS(pos.y), METERS_TO_PIXELS(shape->m_radius), 255, 255, 255); } break; // Draw polygons ------------------------------------------------ case b2Shape::e_polygon: { b2PolygonShape* polygonShape = (b2PolygonShape*)f->GetShape(); int32 count = polygonShape->GetVertexCount(); b2Vec2 prev, v; for(int32 i = 0; i < count; ++i) { v = b->GetWorldPoint(polygonShape->GetVertex(i)); if(i > 0) App->renderer->DrawLine(METERS_TO_PIXELS(prev.x), METERS_TO_PIXELS(prev.y), METERS_TO_PIXELS(v.x), METERS_TO_PIXELS(v.y), 255, 100, 100); prev = v; } v = b->GetWorldPoint(polygonShape->GetVertex(0)); App->renderer->DrawLine(METERS_TO_PIXELS(prev.x), METERS_TO_PIXELS(prev.y), METERS_TO_PIXELS(v.x), METERS_TO_PIXELS(v.y), 255, 100, 100); } break; // Draw chains contour ------------------------------------------- case b2Shape::e_chain: { b2ChainShape* shape = (b2ChainShape*)f->GetShape(); b2Vec2 prev, v; for(int32 i = 0; i < shape->m_count; ++i) { v = b->GetWorldPoint(shape->m_vertices[i]); if(i > 0) App->renderer->DrawLine(METERS_TO_PIXELS(prev.x), METERS_TO_PIXELS(prev.y), METERS_TO_PIXELS(v.x), METERS_TO_PIXELS(v.y), 100, 255, 100); prev = v; } v = b->GetWorldPoint(shape->m_vertices[0]); App->renderer->DrawLine(METERS_TO_PIXELS(prev.x), METERS_TO_PIXELS(prev.y), METERS_TO_PIXELS(v.x), METERS_TO_PIXELS(v.y), 100, 255, 100); } break; // Draw a single segment(edge) ---------------------------------- case b2Shape::e_edge: { b2EdgeShape* shape = (b2EdgeShape*)f->GetShape(); b2Vec2 v1, v2; v1 = b->GetWorldPoint(shape->m_vertex0); v1 = b->GetWorldPoint(shape->m_vertex1); App->renderer->DrawLine(METERS_TO_PIXELS(v1.x), METERS_TO_PIXELS(v1.y), METERS_TO_PIXELS(v2.x), METERS_TO_PIXELS(v2.y), 100, 100, 255); } break; } } } return UPDATE_CONTINUE; }
update_status ModulePhysics::PostUpdate() { if (App->input->GetKey(SDL_SCANCODE_F1) == KEY_DOWN) debug = !debug; if (!debug) return UPDATE_CONTINUE; b2Vec2 mouse_position(0, 0); click_body = NULL; // Bonus code: this will iterate all objects in the world and draw the circles // You need to provide your own macro to translate meters to pixels for (b2Body* b = world->GetBodyList(); b; b = b->GetNext()) { for (b2Fixture* f = b->GetFixtureList(); f; f = f->GetNext()) { switch (f->GetType()) { // Draw circles ------------------------------------------------ case b2Shape::e_circle: { b2CircleShape* shape = (b2CircleShape*)f->GetShape(); b2Vec2 pos = f->GetBody()->GetPosition(); App->renderer->DrawCircle(METERS_TO_PIXELS(pos.x), METERS_TO_PIXELS(pos.y), METERS_TO_PIXELS(shape->m_radius), 255, 255, 255); } break; // Draw polygons ------------------------------------------------ case b2Shape::e_polygon: { b2PolygonShape* polygonShape = (b2PolygonShape*)f->GetShape(); int32 count = polygonShape->GetVertexCount(); b2Vec2 prev, v; for (int32 i = 0; i < count; ++i) { v = b->GetWorldPoint(polygonShape->GetVertex(i)); if (i > 0) App->renderer->DrawLine(METERS_TO_PIXELS(prev.x), METERS_TO_PIXELS(prev.y), METERS_TO_PIXELS(v.x), METERS_TO_PIXELS(v.y), 255, 100, 100); prev = v; } v = b->GetWorldPoint(polygonShape->GetVertex(0)); App->renderer->DrawLine(METERS_TO_PIXELS(prev.x), METERS_TO_PIXELS(prev.y), METERS_TO_PIXELS(v.x), METERS_TO_PIXELS(v.y), 255, 100, 100); } break; // Draw chains contour ------------------------------------------- case b2Shape::e_chain: { b2ChainShape* shape = (b2ChainShape*)f->GetShape(); b2Vec2 prev, v; for (int32 i = 0; i < shape->m_count; ++i) { v = b->GetWorldPoint(shape->m_vertices[i]); if (i > 0) App->renderer->DrawLine(METERS_TO_PIXELS(prev.x), METERS_TO_PIXELS(prev.y), METERS_TO_PIXELS(v.x), METERS_TO_PIXELS(v.y), 100, 255, 100); prev = v; } v = b->GetWorldPoint(shape->m_vertices[0]); App->renderer->DrawLine(METERS_TO_PIXELS(prev.x), METERS_TO_PIXELS(prev.y), METERS_TO_PIXELS(v.x), METERS_TO_PIXELS(v.y), 100, 255, 100); } break; // Draw a single segment(edge) ---------------------------------- case b2Shape::e_edge: { b2EdgeShape* shape = (b2EdgeShape*)f->GetShape(); b2Vec2 v1, v2; v1 = b->GetWorldPoint(shape->m_vertex0); v1 = b->GetWorldPoint(shape->m_vertex1); App->renderer->DrawLine(METERS_TO_PIXELS(v1.x), METERS_TO_PIXELS(v1.y), METERS_TO_PIXELS(v2.x), METERS_TO_PIXELS(v2.y), 100, 100, 255); } break; } // MOUSE JOINT if (App->input->GetMouseButton(SDL_BUTTON_LEFT) == KEY_DOWN) { mouse_position.x = PIXEL_TO_METERS(App->input->GetMouseX()); mouse_position.y = PIXEL_TO_METERS(App->input->GetMouseY()); if (f->GetShape()->TestPoint(b->GetTransform(), mouse_position) == true) { click_body = f->GetBody(); LOG("body_clicked\n"); } } } } // creation of the joint if (click_body != NULL) { b2MouseJointDef def; def.bodyA = ground; def.bodyB = click_body; def.target = mouse_position; def.dampingRatio = 0.5f; def.frequencyHz = 20.0f; def.maxForce = 100.0f * click_body->GetMass(); mouse_joint = (b2MouseJoint*)world->CreateJoint(&def); } if (mouse_joint != NULL && App->input->GetMouseButton(SDL_BUTTON_LEFT) == KEY_REPEAT) { b2Vec2 posA, posB; posA = mouse_joint->GetAnchorA(); posB.x = PIXEL_TO_METERS(App->input->GetMouseX()); posB.y = PIXEL_TO_METERS(App->input->GetMouseY()); mouse_joint->SetTarget(posB); } if (mouse_joint != NULL && App->input->GetMouseButton(SDL_BUTTON_LEFT) == KEY_UP) { world->DestroyJoint(mouse_joint); mouse_joint = NULL; } return UPDATE_CONTINUE; }
update_status ModulePhysics::PostUpdate() { // On space bar press, create a circle on mouse position if(App->input->GetKey(SDL_SCANCODE_1) == KEY_DOWN) { CreateCircle(App->input->GetMouseX(), App->input->GetMouseY(), 25); } if(App->input->GetKey(SDL_SCANCODE_2) == KEY_DOWN) { CreateBox(75, 3); } if(App->input->GetKey(SDL_SCANCODE_3) == KEY_DOWN) { // TODO 3: Create a chain shape using those vertices // remember to convert them from pixels to meters! int points[66] = { 1, 76, 29, 62, 14, 35, 42, 38, 41, 0, 75, 31, 87, 4, 94, 40, 112, 34, 105, 62, 116, 66, 109, 73, 110, 80, 109, 85, 105, 93, 110, 99, 103, 104, 100, 116, 105, 124, 99, 131, 91, 142, 81, 149, 72, 149, 60, 147, 50, 138, 45, 133, 34, 136, 39, 126, 23, 124, 30, 114, 10, 103, 27, 91, 1, 76 }; b2Vec2 vs[33]; for (int i = 0, j = 0; j < 33; i+=2, j++) vs[j].Set(PIXEL_TO_METERS(points[i]), PIXEL_TO_METERS(points[i+1])); b2BodyDef H; H.type = b2_dynamicBody; H.position.Set(PIXEL_TO_METERS(App->input->GetMouseX()), PIXEL_TO_METERS(App->input->GetMouseY())); b2Body* b3 = world->CreateBody(&H); b2ChainShape shape_chain; b2FixtureDef fixture_chain; fixture_chain.shape = &shape_chain; fixture_chain.density = 1.0f; shape_chain.CreateLoop(vs, 32); b3->CreateFixture(&fixture_chain); } if(App->input->GetKey(SDL_SCANCODE_F1) == KEY_DOWN) debug = !debug; if(!debug) return UPDATE_CONTINUE; // Bonus code: this will iterate all objects in the world and draw the circles // You need to provide your own macro to translate meters to pixels for(b2Body* b = world->GetBodyList(); b; b = b->GetNext()) { for(b2Fixture* f = b->GetFixtureList(); f; f = f->GetNext()) { switch(f->GetType()) { // Draw circles ------------------------------------------------ case b2Shape::e_circle: { b2CircleShape* shape = (b2CircleShape*)f->GetShape(); b2Vec2 pos = f->GetBody()->GetPosition(); App->renderer->DrawCircle(METERS_TO_PIXELS(pos.x), METERS_TO_PIXELS(pos.y), METERS_TO_PIXELS(shape->m_radius), 255, 255, 255); } break; // Draw polygons ------------------------------------------------ case b2Shape::e_polygon: { b2PolygonShape* polygonShape = (b2PolygonShape*)f->GetShape(); int32 count = polygonShape->GetVertexCount(); b2Vec2 prev, v; for(int32 i = 0; i < count; ++i) { v = b->GetWorldPoint(polygonShape->GetVertex(i)); if(i > 0) App->renderer->DrawLine(METERS_TO_PIXELS(prev.x), METERS_TO_PIXELS(prev.y), METERS_TO_PIXELS(v.x), METERS_TO_PIXELS(v.y), 255, 100, 100); prev = v; } v = b->GetWorldPoint(polygonShape->GetVertex(0)); App->renderer->DrawLine(METERS_TO_PIXELS(prev.x), METERS_TO_PIXELS(prev.y), METERS_TO_PIXELS(v.x), METERS_TO_PIXELS(v.y), 255, 100, 100); } break; // Draw chains contour ------------------------------------------- case b2Shape::e_chain: { b2ChainShape* shape = (b2ChainShape*)f->GetShape(); b2Vec2 prev, v; for(int32 i = 0; i < shape->m_count; ++i) { v = b->GetWorldPoint(shape->m_vertices[i]); if(i > 0) App->renderer->DrawLine(METERS_TO_PIXELS(prev.x), METERS_TO_PIXELS(prev.y), METERS_TO_PIXELS(v.x), METERS_TO_PIXELS(v.y), 100, 255, 100); prev = v; } v = b->GetWorldPoint(shape->m_vertices[0]); App->renderer->DrawLine(METERS_TO_PIXELS(prev.x), METERS_TO_PIXELS(prev.y), METERS_TO_PIXELS(v.x), METERS_TO_PIXELS(v.y), 100, 255, 100); } break; // Draw a single segment(edge) ---------------------------------- case b2Shape::e_edge: { b2EdgeShape* shape = (b2EdgeShape*)f->GetShape(); b2Vec2 v1, v2; v1 = b->GetWorldPoint(shape->m_vertex0); v1 = b->GetWorldPoint(shape->m_vertex1); App->renderer->DrawLine(METERS_TO_PIXELS(v1.x), METERS_TO_PIXELS(v1.y), METERS_TO_PIXELS(v2.x), METERS_TO_PIXELS(v2.y), 100, 100, 255); } break; } } } return UPDATE_CONTINUE; }