// Exercise the RR's contains rect method static void test_round_rect_contains_rect(skiatest::Reporter* reporter) { static const int kNumRRects = 4; static const SkVector gRadii[kNumRRects][4] = { { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, // rect { { 20, 20 }, { 20, 20 }, { 20, 20 }, { 20, 20 } }, // circle { { 10, 10 }, { 10, 10 }, { 10, 10 }, { 10, 10 } }, // simple { { 0, 0 }, { 20, 20 }, { 10, 10 }, { 30, 30 } } // complex }; SkRRect rrects[kNumRRects]; for (int i = 0; i < kNumRRects; ++i) { rrects[i].setRectRadii(SkRect::MakeWH(40, 40), gRadii[i]); } // First test easy outs - boxes that are obviously out on // each corner and edge static const SkRect easyOuts[] = { { -5, -5, 5, 5 }, // NW { 15, -5, 20, 5 }, // N { 35, -5, 45, 5 }, // NE { 35, 15, 45, 20 }, // E { 35, 45, 35, 45 }, // SE { 15, 35, 20, 45 }, // S { -5, 35, 5, 45 }, // SW { -5, 15, 5, 20 } // W }; for (int i = 0; i < kNumRRects; ++i) { for (size_t j = 0; j < SK_ARRAY_COUNT(easyOuts); ++j) { REPORTER_ASSERT(reporter, !rrects[i].contains(easyOuts[j])); } } // Now test non-trivial containment. For each compass // point walk a 1x1 rect in from the edge of the bounding // rect static const int kNumSteps = 15; bool answers[kNumRRects][8][kNumSteps] = { // all the test rects are inside the degenerate rrect { // rect { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, }, // for the circle we expect 6 blocks to be out on the // corners (then the rest in) and only the first block // out on the vertical and horizontal axes (then // the rest in) { // circle { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, }, // for the simple round rect we expect 3 out on // the corners (then the rest in) and no blocks out // on the vertical and horizontal axes { // simple RR { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, }, // for the complex case the answer is different for each direction { // complex RR // all in for NW (rect) corner (same as rect case) { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // only first block out for N (same as circle case) { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // first 6 blocks out for NE (same as circle case) { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // only first block out for E (same as circle case) { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // first 3 blocks out for SE (same as simple case) { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // first two blocks out for S { 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // first 9 blocks out for SW { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1 }, // first two blocks out for W (same as S) { 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, } }; for (int i = 0; i < kNumRRects; ++i) { test_direction(reporter, rrects[i], 0, 1, 0, 1, kNumSteps, answers[i][0]); // NW test_direction(reporter, rrects[i], 19.5f, 0, 0, 1, kNumSteps, answers[i][1]); // N test_direction(reporter, rrects[i], 40, -1, 0, 1, kNumSteps, answers[i][2]); // NE test_direction(reporter, rrects[i], 40, -1, 19.5f, 0, kNumSteps, answers[i][3]); // E test_direction(reporter, rrects[i], 40, -1, 40, -1, kNumSteps, answers[i][4]); // SE test_direction(reporter, rrects[i], 19.5f, 0, 40, -1, kNumSteps, answers[i][5]); // S test_direction(reporter, rrects[i], 0, 1, 40, -1, kNumSteps, answers[i][6]); // SW test_direction(reporter, rrects[i], 0, 1, 19.5f, 0, kNumSteps, answers[i][7]); // W } }
void BallMovement::bounce(bool collision) { if (stop_speed != 0) return; #ifdef CHOWDREN_IS_AVGN fix_position(); int direction = instance->direction; float angle = rad(direction * 11.25f); float found_a = -1.0f; for (float a = 0.0f; a < (CHOW_PI*2.0f); a += (CHOW_PI*2.0f) / 16.0f) { float x_move = 10.0f * cos(angle + a); float y_move = -10.0f * sin(angle + a); int x = instance->x + x_move; int y = instance->y + y_move; if (!test_position(x, y)) { found_a = a; break; } } if (found_a == -1.0f) { instance->set_direction((instance->direction + 16) % 32, false); return; } angle += found_a * 2.0f; if (angle > 2.0 * CHOW_PI) angle -= 2.0 * CHOW_PI; instance->set_direction(deg(angle) / 11.25f, false); if (back_col) instance->flags &= ~REPEAT_BACK_COLLISION; else instance->collision_flags = 0; #else add_x = add_y = 0; if (collision) { if (back_col) has_back_col = true; push_out(); } int x = instance->x; int y = instance->y; x -= 8; y -= 8; int rebond = 0; if (test_position(x, y)) rebond |= 0x01; x += 16; if (test_position(x, y)) rebond |= 0x02; y += 16; if (test_position(x, y)) rebond |= 0x04; x -= 16; if (test_position(x, y)) rebond |= 0x08; int value = rebond_list[rebond * 32 + instance->direction]; if (test_direction(value, 8)) { int angles = 4; int angles2 = angles; bool is_free = false; while (true) { value -= angles; value &= 31; if (!test_direction(value, 8)) { is_free = true; break; } value += 2 * angles; value &= 31; if (!test_direction(value, 8)) { is_free = true; break; } value -= angles; value &= 31; angles += angles2; if (angles <= 16) break; } if (!is_free) value = randrange(32); } int rnd = randrange(100); if (rnd < randomizer) { rnd >>= 2; if (rnd < 25) { rnd -= 12; rnd &= 31; if (!test_direction(rnd, 8)) value = rnd; } }