Exemple #1
0
// compute velocity & position (cube included) and draw dot (exploded or not)
void Cube::animate(Cube* cubes, const float dts) {
    static const float deadzone = 2.0f;
    static const float accelScale = 0.6f;
    static const float damping = 0.995f;

    if (lifeCounter <= 0)
        return;

    for (uint8_t d=0; d<dot_n; d++) {
        // if dot neither hidden nor exploded, animate it:
        if (not (vid.sprites[d].isHidden() || dots[d].exp)) {
            Float2 accel = id.accel().xy();
            if (accel.len2() > deadzone * deadzone)
                dots[d].vel += accel * accelScale;
            dots[d].vel *= damping;
            Float2 step = dots[d].vel * dts;
            Float2 candidate = dots[d].pos + step;

            // Does this dot want to leave the cube ?
            Side mySide = (candidate.y < minPos.y) ? TOP    : //  0
                          (candidate.x < minPos.x) ? LEFT   : //  1
                          (candidate.y > maxPos.y) ? BOTTOM : //  2
                          (candidate.x > maxPos.x) ? RIGHT  : //  3
                          NO_SIDE; // -1
            bool stayHere = true;   // default
            CubeID hisID;           // neighbor CubeID
            Side hisSide = NO_SIDE; // his side number that touches mySide

            if (mySide != NO_SIDE) {          // avoids cubeAt(NO_SIDE) error
                Neighborhood myNbh(id);
                hisID = myNbh.cubeAt(mySide);
                if (hisID.isDefined()) {      // ...same with sideOf(NO_SIDE)
                    Neighborhood hisNbh(hisID);
                    hisSide = hisNbh.sideOf(id);
                    stayHere = cubes[hisID].isFull();
                }
            }
            if (stayHere) {                         // will this dot stay?
                if (mySide==TOP || mySide==BOTTOM)  // bounce vertically?
                    dots[d].vel.y = -dots[d].vel.y;
                if (mySide==LEFT || mySide==RIGHT)  // ...horizontally?
                    dots[d].vel.x = -dots[d].vel.x;

                dots[d].pos += dots[d].vel * dts;   // finish calculation
                vid.sprites[d].setImage(DotIMG);    // draw the dot
                vid.sprites[d].move(dots[d].pos);
            } else {                                // move to neighbor
                dots[d].pos += step;                // finish calculation
                moveDot(d, cubes[hisID], mySide, hisSide);
            }
        }
    }
    collisionCheck();
    displayDamages();
}
Exemple #2
0
RGB565 calculateMandelbrot(UInt2 pixel)
{
    /*
     * Calculate one pixel of a Mandelbrot fractal,
     * using continuous shading based on a renormalizing technique.
     *
     * Reference: http://linas.org/art-gallery/escape/escape.html
     */

    const float radius2 = 400.f;
    const unsigned maxIters = 12;
    const float scale = 0.022f;
    const Int2 center = LCD_center + vec(25, 0);

    // We use Float2 vectors to store complex numbers
    Float2 z = vec(0, 0);
    Float2 c = (pixel - center) * scale;
    unsigned iters = 0;
    float modulus2;

    // Traditional Mandelbrot iteration
    do {
        z = z.cmul(z) + c;
        modulus2 = z.len2();
    } while (++iters <= maxIters && modulus2 <= radius2);

    // A couple extra iterations
    z = z.cmul(z) + c;
    z = z.cmul(z) + c;
    iters += 2;

    // Continuous shading, taking into account the iteration number as well
    // as how far outside the escape radius we are.
    float mu = (iters - log(log(z.len())) / M_LN2) / maxIters;

    if (mu < 1.0f) {
        // Exterior of fractal
        return calculateColorPalette(mu);
    } else {
        // Interior (didn't escape within our limit, or NaN)
        return RGB565::fromRGB(0x000000);
    }
}
Exemple #3
0
// check distance between dots and mark them as exploded if too close
void Cube::collisionCheck() {
    for (uint8_t i=0; i<dot_n; i++)
        if (not vid.sprites[i].isHidden() && !dots[i].exp)
            for (uint8_t j=i+1; j<dot_n; j++)
                if (not vid.sprites[j].isHidden() && !dots[i].exp)  {
                    Float2 dif = dots[i].pos - dots[j].pos;
                    // are the dots too close ?
                    if (dif.len2() < SPR_size.len2()/4) {
                        dots[i].pos -= dif/2; // bring dots closer
                        dots[j].pos += dif/2; // to each other
                        dots[i].exp = exploDuration;
                        dots[j].exp = exploDuration;
#if ACCURATE == 1
                        // use a binary map to check if we hit or miss Conan:
                        dots[i].bnd = isHit(dots[i].pos);
                        dots[j].bnd = isHit(dots[j].pos);
#else
                        // ...or use a FlatAssetImage but it's less accurate:
                        Float2 o = SPR_size/2; // offset to sprite center
                        uint16_t linPosI = uint16_t( (dots[i].pos.x+o.x)/8 ) +
                                           uint16_t( (dots[i].pos.y+o.y)/8 ) *
                                           ConanIMG.tileWidth() ;
                        uint16_t linPosJ = uint16_t( (dots[j].pos.x+o.x)/8 ) +
                                           uint16_t( (dots[j].pos.y+o.y)/8 ) *
                                           ConanIMG.tileWidth() ;
                        // D'oh! need band aid ?
                        dots[i].bnd = (ConanIMG.tile(linPosI) != whiteTile);
                        dots[j].bnd = (ConanIMG.tile(linPosJ) != whiteTile &&
                                       linPosJ  != linPosI);
#endif
                        // D'oh! need band aid ?
                        if (dots[i].bnd)
                            lifeCounter -= 5;
                        if (dots[j].bnd)
                            lifeCounter -= 5;
                    }
                }

    if (lifeCounter <= 0)
        win();
}