bool Rotation::post_compose(Origin origin) { PointSet tps,tps2; tps.owner=this; tps2.owner=this; Point tp,tp2,tp3; std::vector<PointSet> tpsv; origin.angle = normalise_angle(PI+origin.angle+angles[0]); // Now the extra rotation magic... for( auto iter=composed_points.begin(); iter!=composed_points.end();++iter) { tps = *iter; tps2=*iter; tps2.points.clear(); for(auto magnumpi=tps.points.begin();magnumpi!=tps.points.end();++magnumpi) { if((tps.render_flags&RENDER_SURFACE)>0) { tp=*magnumpi; if( magnumpi - tps.points.begin() < 1 ) { tp2=*magnumpi; tp.x=origin.position.x-tp.x; tp.y=origin.position.y-tp.y; tp2.x=tp.x*cos(origin.angle)-tp.y*sin(origin.angle); tp2.y=tp.x*sin(origin.angle)+tp.y*cos(origin.angle); tp2.x+=origin.position.x; tp2.y+=origin.position.y; tp=tp2; } else { } tps2.points.push_back(tp); // This is a special case for surfaces as they are rotated and scaled differently } else { tp=*magnumpi; tp.x=origin.position.x-tp.x; tp.y=origin.position.y-tp.y; tp2.x=tp.x*cos(origin.angle)-tp.y*sin(origin.angle); tp2.y=tp.x*sin(origin.angle)+tp.y*cos(origin.angle); tp2.x+=origin.position.x; tp2.y+=origin.position.y; tps2.points.push_back(tp2); } } if((tps2.render_flags&RENDER_SURFACE)>0) { Element* argh=static_cast<Element*>(tps2.owner); if( argh->inherit_angle ) { tps2.surface_angle += (normalise_angle(origin.angle-PI-angles[0]) * (180/PI)); } //cout << "Composed surface: " << tps2.points[0].x << ", " << tps2.points[0].y << ", " << tps2.points[1].x << ", " << tps2.points[1].y << ", @" << tps2.surface_angle << "(origin says " << origin.angle << ")" << endl; } tpsv.push_back(tps2); } composed_points=tpsv; return false; // Composition is good to go! }
bool Container::pre_compose(Origin origin) { composed_points.clear(); if(!inherit_position) { origin.position.x=0.0; origin.position.y=0.0; } if(!inherit_scale) { origin.scale.x=1.0; origin.scale.y=1.0; } if(!inherit_angle) { origin.angle=0.0; } if(calc_rel_pos) { origin.position.x+=geometry[0]; origin.position.y+=geometry[1]; } else { origin.position.x=geometry[0]; origin.position.y=geometry[1]; } if(calc_rel_scale) { origin.scale.x *= scale[0]; origin.scale.y *= scale[1]; } else { origin.scale.x=scale[0]; origin.scale.y=scale[1]; } if(calc_rel_rot) { origin.angle += angles[0]; // Not interested in passing on rotation as we'll do this after... } else { origin.angle = normalise_angle(angles[0]); } // Element* el; for(auto iter=contents.begin(); iter!=contents.end();++iter) { // Now we compose each child element... auto el2=*iter; el2->compose(origin); composed_points.insert(composed_points.end(),el2->composed_points.cbegin(),el2->composed_points.cend()); el2->composed_points.clear(); } return false; }
/* Check if the ball will collide with something if it is moved to the * specified coordinates. If so, the direction is changed and 1 is returned * to indicate that the caller should recalculate the new coordinates and * try again. If there was no collision it returns 0. If something exceptional * happens (eg. the last brick is destroyed or the last ball is lost) it * returns 2 to indicate that the caller should give up trying to move the * ball. */ int check_ball_collision(nbstate *state, coords *c) { int i, bc; grid *g = state->grid; /* Check for a collision with the top of the game area: */ if(c->y < state->ball.s->h + (2 * BALLS_BORDER) + state->scores.h) { /* Bounce the ball back down and ask the caller to try again: */ state->ball.d = normalise_angle(M_PI - state->ball.d); return 1; } /* Check for a collision with the bottom of the game area: */ if(c->y > state->canvasheight - state->ball.s->h) { /* If the solidfloor cheat is active, bounce the ball back up * and ask the caller to try again: */ if(state->flags.sf) { state->ball.d = normalise_angle(M_PI - state->ball.d); return 1; } else { /* Otherwise destroy the ball, move the new ball to * the parked position (park_ball() is called by * lost_ball()) and ask the caller to give up trying * to move the ball: */ lost_ball(state); move_ball(state); return 2; } } /* Check for a collision with the left hand side of the game area: */ if(c->x < 0) { /* Bounce the ball back and ask the caller to try again: */ state->ball.d = normalise_angle((2 * M_PI) - state->ball.d); return 1; } /* Check for a collision with the right hand side of the game area: */ if(c->x > state->canvaswidth - state->ball.s->w) { /* Bounce the ball back and ask the caller to try again: */ state->ball.d = normalise_angle((2 * M_PI) - state->ball.d); return 1; } /* Check for a collision with the bat: */ if(c->y > state->canvasheight - state->batheight - state->ball.s->h && c->x > state->batx - (state->batwidths[state->bat] / 2) - state->ball.s->w && c->x < state->batx + (state->batwidths[state->bat] / 2)) { /* If the collision happened with the side of the bat instead * of the top, we don't care so just tell the caller there * was no collision: */ if(state->ball.y > state->canvasheight - state->batheight - state->ball.s->h) return 0; /* If the StickyBat power-up is active, park the ball: */ if(state->powertimes.stickybat) { park_ball(state); move_ball(state); return 2; } else { /* Otherwise bounce it back up and ask the caller to * try again: */ state->ball.d = normalise_angle(((c->x + (state->ball.s->w / 2) - state->batx) / state->batwidths[state->bat] / 2) * M_PI); return 1; } } /* Check for collisions with the bricks: */ bc = 0; /* No collisions have happened yet. */ /* For each brick in the grid: */ for(i = 0; i < state->width * state->height; i++) { /* If there is a brick in this grid position and the ball * intersects it: */ if(g->b && c->y + state->ball.s->h > g->y && c->y < g->y + state->brickheight && c->x + state->ball.s->w > g->x && c->x < g->x + state->brickwidth) { /* Perform the brick collision actions, and if * something exceptional happens (ie. we destroy the * last brick), return straight away asking the caller * to give up trying to move the ball: */ if(brick_collision(state, g)) return 2; /* Unless the NoBounce cheat is active, bounce the * ball off the brick. Only do this on the first brick * collision we find. */ if(!state->flags.nb && !bc) { bc = 1; /* Bounce off the left face: */ if(state->ball.x + state->ball.s->w < g->x) { state->ball.d = normalise_angle((2 * M_PI) - state->ball.d); /* Bounce off the right face: */ } else if(state->ball.x >= g->x + state->brickwidth) { state->ball.d = normalise_angle((2 * M_PI) - state->ball.d); /* Bounce off the upper face: */ } else if(state->ball.y + state->ball.s->h < g->y) { state->ball.d = normalise_angle(M_PI - state->ball.d); /* Bounce off the lower face: */ } else if(state->ball.y >= g->y + state->brickheight) { state->ball.d = normalise_angle(M_PI - state->ball.d); } else { /* This shouldn't happen, but I don't * trust the above algorithm 100%. */ debug_printf ("Internal error: " "couldn't figure out brick " "collision face\n"); } } } g++; /* Increment to the next grid position. */ } /* If a brick collision occured, ask the caller to try again: */ if(bc) return 1; return 0; /* Otherwise tell the caller that no collision occured. */ }