示例#1
0
void AppBody()
{
    bool done = false;
    bool redraw = false;

    TileMap map("data/maps/test1.tmx");
    Sprite sprt("data/sprites/demo.adf");
    sprt.SendNewState(AnimState::IDLE, AnimDir::DOWN);

    ALLEGRO_TRANSFORM camera;

    int x_offset = 0, y_offset = 0;
    int x_delta, y_delta;
    int key_state[2] = {0, 0};

    x_delta = applicationConfig.iDispW - al_get_bitmap_width(map.GetFullMap());
    y_delta = applicationConfig.iDispH - al_get_bitmap_height(map.GetFullMap());

    Vec2D playerPos {0, 0};
    Vec2D playerVel {0, 0};

    al_start_timer(timer);
    while (!done)
    {
        ALLEGRO_EVENT ev;
        al_wait_for_event(queue, &ev);

        switch (ev.type)
        {
            case ALLEGRO_EVENT_TIMER:
                al_identity_transform(&camera);

                x_offset += key_state[0];
                y_offset += key_state[1];

                if (x_delta > 0)
                {
                    x_offset = x_delta / 2;
                } else
                {
                    if (x_offset < x_delta) x_offset = x_delta;
                    if (x_offset > 0) x_offset = 0;
                }
                if (y_delta > 0)
                {
                    y_offset = y_delta / 2;
                } else
                {
                    if (y_offset < y_delta) y_offset = y_delta;
                    if (y_offset > 0) y_offset = 0;
                }

                if (map.CanWalktoTileAt(playerPos, sprt.GetSize(), {0.0f, 32.0f}) == true)
                {
                    playerPos = playerPos + playerVel;
                } else
                {
                    Vec2D backtracing = playerVel;
                    playerVel = {0, 0}; // we delete player velocitity to stop oscillating in place during collision.
                    if (backtracing == playerVel) // If for whatever reason we are stuck and cannot determine orig vector... MAGIC!
                    {
                        backtracing.x = 2.0f;
                        backtracing.y = 2.0f;

                        float angle = rand() % 359 + 1;
                        backtracing.rotate(angle * (ALLEGRO_PI / 180));
                        std::cerr << "Warning: Unknown velocity vector. Will use [" << backtracing.x << "," << backtracing.y
                            << "] as direction to solve collision." << std::endl;
                    }

                    while (map.CanWalktoTileAt(playerPos, sprt.GetSize(), {0.0f, 32.0f}) == false)
                    {
                        playerPos = playerPos - backtracing;
                    }
                }

                sprt.Update();
                redraw = true;
                break;
            case ALLEGRO_EVENT_DISPLAY_CLOSE:
                done = true;
                break;
            case ALLEGRO_EVENT_KEY_DOWN:
                if (ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE)
                {
                    done = true;
                }

                switch (ev.keyboard.keycode)
                {
                    case ALLEGRO_KEY_LEFT:  key_state[0] = 4; break;
                    case ALLEGRO_KEY_RIGHT: key_state[0] = -4; break;
                    case ALLEGRO_KEY_UP:    key_state[1] = 4; break;
                    case ALLEGRO_KEY_DOWN:  key_state[1] = -4; break;

                    case ALLEGRO_KEY_A:
                        playerVel.x = -2;
                        sprt.SendNewState(AnimState::MOVE, AnimDir::LEFT);
                        break;
                    case ALLEGRO_KEY_D:
                        playerVel.x = 2;
                        sprt.SendNewState(AnimState::MOVE, AnimDir::RIGHT);
                        break;
                    case ALLEGRO_KEY_W:
                        playerVel.y = -2;
                        sprt.SendNewState(AnimState::MOVE, AnimDir::UP);
                        break;
                    case ALLEGRO_KEY_S:
                        playerVel.y = 2;
                        sprt.SendNewState(AnimState::MOVE, AnimDir::DOWN);
                        break;
                }

                break;
            case ALLEGRO_EVENT_KEY_UP:
                switch (ev.keyboard.keycode)
                {
                    case ALLEGRO_KEY_LEFT:
                    case ALLEGRO_KEY_RIGHT: key_state[0] = 0; break;
                    case ALLEGRO_KEY_UP:
                    case ALLEGRO_KEY_DOWN:  key_state[1] = 0; break;

                    case ALLEGRO_KEY_A:
                        playerVel.x = 0;
                        sprt.SendNewState(AnimState::IDLE, AnimDir::LEFT);
                        break;
                    case ALLEGRO_KEY_D:
                        playerVel.x = 0;
                        sprt.SendNewState(AnimState::IDLE, AnimDir::RIGHT);
                        break;
                    case ALLEGRO_KEY_W:
                        playerVel.y = 0;
                        sprt.SendNewState(AnimState::IDLE, AnimDir::UP);
                        break;
                    case ALLEGRO_KEY_S:
                        playerVel.y = 0;
                        sprt.SendNewState(AnimState::IDLE, AnimDir::DOWN);
                        break;
                }
                break;
            default:
                break;
        }

        if (redraw && al_is_event_queue_empty(queue))
        {
            al_translate_transform(&camera, x_offset, y_offset);
            al_use_transform(&camera);

            redraw = false;
            al_clear_to_color(styleConfig.colBackgroundColor);

            map.DrawLayerMap("Background");
            map.DrawLayerMap("Foreground");
            /*
            Playable characters should draw on this position
            */
            sprt.Render(playerPos.x, playerPos.y);
            map.DrawLayerMap("Top");

            al_flip_display();
        }
    }
}