/*! */ void PlayerControlPainter::draw( QPainter & painter ) { const Options & opt = Options::instance(); if ( ! opt.showKickAccelArea() ) { return; } int number = opt.selectedNumber(); if ( number == 0 ) { return; } MonitorViewConstPtr view = M_main_data.getCurrentViewData(); if ( ! view ) { return; } const Ball & ball = view->ball(); if ( ! ball.hasDelta() ) { return; } const rcsc::ServerParam & SP = rcsc::ServerParam::i(); const DrawConfig & dconf = DrawConfig::instance(); const Player & player = view->players()[ ( number > 0 ? number - 1 : -number - 1 + 11 ) ]; const rcsc::PlayerType & ptype = M_main_data.viewHolder().playerType( player.type() ); rcsc::Vector2D ppos( player.x(), player.y() ); rcsc::Vector2D bpos( ball.x(), ball.y() ); rcsc::Vector2D player_to_ball = bpos - ppos; player_to_ball.rotate( - player.body() ); rcsc::Vector2D bnext( bpos.x + ball.deltaX(), bpos.y + ball.deltaY() ); double ball_dist = player_to_ball.r(); if ( ball_dist < ptype.kickableArea() ) { double max_kick_accel = SP.maxPower() //* SP.kickPowerRate() * ptype.kickPowerRate() * ( 1.0 - 0.25 * player_to_ball.th().abs() / 180.0 - 0.25 * ( ball_dist - ptype.playerSize() - SP.ballSize() ) / ptype.kickableMargin() ); if ( max_kick_accel > SP.ballAccelMax() ) { max_kick_accel = SP.ballAccelMax(); } QPointF bpos_screen( opt.screenXF( bpos.x ), opt.screenYF( bpos.y ) ); QPointF bnext_screen( opt.screenXF( bnext.x ), opt.screenYF( bnext.y ) ); double max_speed_screen = opt.scaleF( SP.ballSpeedMax() ); double max_kick_accel_screen = opt.scaleF( max_kick_accel ); painter.setPen( dconf.kickAccelPen() ); painter.setBrush( dconf.transparentBrush() ); // draw no noise next ball move only by inertia painter.drawLine( QLineF( bpos_screen, bnext_screen ) ); rcsc::Circle2D max_speed_circle( bpos, SP.ballSpeedMax() ); rcsc::Circle2D max_accel_circle( bnext, max_kick_accel ); rcsc::Vector2D intersection_1, intersection_2; if ( max_speed_circle.intersection( max_accel_circle, &intersection_1, &intersection_2 ) != 2 ) { // no intersection points // just draw a next ball reachable area by max accel painter.drawEllipse( QRectF( bnext_screen.x() - max_kick_accel_screen, bnext_screen.y() - max_kick_accel_screen, max_kick_accel_screen * 2, max_kick_accel_screen * 2 ) ); } else { // exists 2 intersection points rcsc::AngleDeg bpos_to_intersection_1 = ( intersection_1 - bpos ).th(); rcsc::AngleDeg bpos_to_intersection_2 = ( intersection_2 - bpos ).th(); rcsc::AngleDeg bpos_to_bnext_angle = ( bnext - bpos ).th(); rcsc::AngleDeg * bpos_start_angle = 0; double bpos_angle_span = 0.0; if ( bpos_to_intersection_1.isLeftOf( bpos_to_bnext_angle ) ) { bpos_start_angle = &bpos_to_intersection_1; bpos_angle_span = ( bpos_to_intersection_2 - bpos_to_intersection_1 ).degree(); if ( bpos_angle_span < 0.0 ) { bpos_angle_span += 360.0; } bpos_angle_span *= -1.0; } else { bpos_start_angle = &bpos_to_intersection_2; bpos_angle_span = ( bpos_to_intersection_1 - bpos_to_intersection_2 ).degree(); if ( bpos_angle_span < 0.0 ) { bpos_angle_span += 360.0; } bpos_angle_span *= -1.0; } if ( opt.reverseSide() ) { *bpos_start_angle += 180.0; } int bpos_start_angle_int = static_cast< int >( rint( - bpos_start_angle->degree() * 16 ) ); int bpos_angle_span_int = static_cast< int >( rint( bpos_angle_span * 16 ) ); painter.drawArc( QRectF( bpos_screen.x() - max_speed_screen, bpos_screen.y() - max_speed_screen, max_speed_screen * 2, max_speed_screen * 2 ), bpos_start_angle_int, bpos_angle_span_int ); rcsc::AngleDeg bnext_to_intersection_1 = ( intersection_1 - bnext ).th(); rcsc::AngleDeg bnext_to_intersection_2 = ( intersection_2 - bnext ).th(); rcsc::AngleDeg bnext_to_bpos_angle = bpos_to_bnext_angle + 180.0; rcsc::AngleDeg * bnext_start_angle = 0; double bnext_angle_span = 0.0; if ( bnext_to_intersection_1.isLeftOf( bnext_to_bpos_angle ) ) { bnext_start_angle = &bnext_to_intersection_1; bnext_angle_span = ( bnext_to_intersection_2 - bnext_to_intersection_1 ).degree(); if ( bnext_angle_span < 0.0 ) { bnext_angle_span += 360.0; } bnext_angle_span *= -1.0; } else { bnext_start_angle = &bnext_to_intersection_2; bnext_angle_span = ( bnext_to_intersection_1 - bnext_to_intersection_2 ).degree(); if ( bnext_angle_span < 0.0 ) { bnext_angle_span += 360.0; } bnext_angle_span *= -1.0; } if ( opt.reverseSide() ) { *bnext_start_angle += 180.0; } int bnext_start_angle_int = static_cast< int >( rint( - bnext_start_angle->degree() * 16 ) ); int bnext_angle_span_int = static_cast< int >( rint( bnext_angle_span * 16 ) ); painter.drawArc( QRectF( bnext_screen.x() - max_kick_accel_screen, bnext_screen.y() - max_kick_accel_screen, max_kick_accel_screen * 2, max_kick_accel_screen * 2 ), bnext_start_angle_int, bnext_angle_span_int ); } // draw kick info text painter.setFont( dconf.playerFont() ); painter.setPen( dconf.kickAccelPen() ); //snprintf( buf, 32, "MaxAccel=%.3f", max_kick_accel ); painter.drawText( QPointF( bnext_screen.x() + 10, bnext_screen.y() + painter.fontMetrics().ascent() ), QString( "MaxAccel=%1" ).arg( max_kick_accel, 0, 'g', 4 ) ); } }
/*! */ void PlayerPainter::drawKickAccelArea( QPainter & painter, const PlayerPainter::Param & param ) const { // // draw kick accel area // if ( ! param.ball_.hasVelocity() ) { return; } const Options & opt = Options::instance(); const rcss::rcg::ServerParamT & SP = M_main_data.serverParam(); Vector2D ppos( param.player_.x_, param.player_.y_ ); Vector2D bpos( param.ball_.x_, param.ball_.y_ ); Vector2D player_to_ball = bpos - ppos; player_to_ball.rotate( - param.player_.body_ ); double ball_dist = player_to_ball.r(); if ( ball_dist > ( param.player_type_.player_size_ + param.player_type_.kickable_margin_ + SP.ball_size_ ) ) { return; } double max_kick_accel = SP.max_power_ //* SP.kick_power_rate_ * param.player_type_.kick_power_rate_ * ( 1.0 - 0.25 * player_to_ball.th().abs() / 180.0 - 0.25 * ( ball_dist - param.player_type_.player_size_ - SP.ball_size_ ) / param.player_type_.kickable_margin_ ); if ( max_kick_accel > SP.ball_accel_max_ ) { max_kick_accel = SP.ball_accel_max_; } Vector2D bnext( bpos.x + param.ball_.vx_, bpos.y + param.ball_.vy_ ); QPoint bpos_screen( opt.screenX( bpos.x ), opt.screenY( bpos.y ) ); QPoint bnext_screen( opt.screenX( bnext.x ), opt.screenY( bnext.y ) ); int max_speed_screen = opt.scale( SP.ball_speed_max_ ); int max_kick_accel_screen = opt.scale( max_kick_accel ); painter.setPen( M_kick_accel_pen ); painter.setBrush( Qt::NoBrush ); // draw no noise ball move line painter.drawLine( bpos_screen, bnext_screen ); Circle2D max_speed_circle( bpos, SP.ball_speed_max_ ); Circle2D max_accel_circle( bnext, max_kick_accel ); Vector2D intersection_1, intersection_2; if ( max_speed_circle.intersection( max_accel_circle, &intersection_1, &intersection_2 ) != 2 ) { // no intersection points // just draw a next ball reachable area by max accel painter.drawEllipse( bnext_screen.x() - max_kick_accel_screen, bnext_screen.y() - max_kick_accel_screen, max_kick_accel_screen * 2, max_kick_accel_screen * 2 ); } else { // exists 2 intersection points AngleDeg bpos_to_intersection_1 = ( intersection_1 - bpos ).th(); AngleDeg bpos_to_intersection_2 = ( intersection_2 - bpos ).th(); AngleDeg bpos_to_bnext_angle = ( bnext - bpos ).th(); AngleDeg * bpos_start_angle = 0; double bpos_angle_span = 0.0; if ( bpos_to_intersection_1.isLeftOf( bpos_to_bnext_angle ) ) { bpos_start_angle = &bpos_to_intersection_1; bpos_angle_span = ( bpos_to_intersection_2 - bpos_to_intersection_1 ).degree(); if ( bpos_angle_span < 0.0 ) { bpos_angle_span += 360.0; } bpos_angle_span *= -1.0; } else { bpos_start_angle = &bpos_to_intersection_2; bpos_angle_span = ( bpos_to_intersection_1 - bpos_to_intersection_2 ).degree(); if ( bpos_angle_span < 0.0 ) { bpos_angle_span += 360.0; } bpos_angle_span *= -1.0; } int bpos_start_angle_int = static_cast< int >( rint( - bpos_start_angle->degree() * 16 ) ); int bpos_angle_span_int = static_cast< int >( rint( bpos_angle_span * 16 ) ); painter.drawArc( bpos_screen.x() - max_speed_screen, bpos_screen.y() - max_speed_screen, max_speed_screen * 2, max_speed_screen * 2, bpos_start_angle_int, bpos_angle_span_int ); AngleDeg bnext_to_intersection_1 = ( intersection_1 - bnext ).th(); AngleDeg bnext_to_intersection_2 = ( intersection_2 - bnext ).th(); AngleDeg bnext_to_bpos_angle = bpos_to_bnext_angle + 180.0; AngleDeg * bnext_start_angle = 0; double bnext_angle_span = 0.0; if ( bnext_to_intersection_1.isLeftOf( bnext_to_bpos_angle ) ) { bnext_start_angle = &bnext_to_intersection_1; bnext_angle_span = ( bnext_to_intersection_2 - bnext_to_intersection_1 ).degree(); if ( bnext_angle_span < 0.0 ) { bnext_angle_span += 360.0; } bnext_angle_span *= -1.0; } else { bnext_start_angle = &bnext_to_intersection_2; bnext_angle_span = ( bnext_to_intersection_1 - bnext_to_intersection_2 ).degree(); if ( bnext_angle_span < 0.0 ) { bnext_angle_span += 360.0; } bnext_angle_span *= -1.0; } int bnext_start_angle_int = static_cast< int >( rint( - bnext_start_angle->degree() * 16 ) ); int bnext_angle_span_int = static_cast< int >( rint( bnext_angle_span * 16 ) ); painter.drawArc( bnext_screen.x() - max_kick_accel_screen, bnext_screen.y() - max_kick_accel_screen, max_kick_accel_screen * 2, max_kick_accel_screen * 2, bnext_start_angle_int, bnext_angle_span_int ); } // draw kick info text painter.setFont( M_player_font ); painter.setPen( M_kick_accel_pen ); char buf[32]; snprintf( buf, 32, "MaxAccel=%.3f", max_kick_accel ); painter.drawText( bnext_screen.x() + 10, bnext_screen.y() + painter.fontMetrics().ascent(), QString::fromAscii( buf ) ); }