Subversion Repositories Code-Repo

Rev

Rev 243 | Rev 276 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include "defines.h"
#include "CONTROLLERS.h"
#include "TRON.h"

static TRON_DATA *data_p;

void Tron_Init(TRON_DATA *data) {
    data_p = data;

    // Set starting point
    data_p->p1_body[0] = (TRON_POINT){0,0,7};
    data_p->p2_body[0] = (TRON_POINT){7,7,7};

    data_p->length = 1;
    data_p->delay = 800;

    Cube_Clear();
    Cube_Overlay_Clear();

    // Draw player 1 light trail
    uint32_t index;
    for (index = 0; index < data_p->length - 1; index++) {
        Cube_Set_Pixel(data_p->p1_body[index].z, data_p->p1_body[index].x, data_p->p1_body[index].y, TRON_PLAYER_1_COLOR);
    }
    Cube_Set_Pixel(data_p->p1_body[data_p->length-1].z, data_p->p1_body[data_p->length-1].x, data_p->p1_body[data_p->length-1].y, TRON_PLAYER_1_HEAD);

    // Draw player 2 light trail
    for (index = 0; index < data_p->length - 1; index++) {
        Cube_Set_Pixel(data_p->p2_body[index].z, data_p->p2_body[index].x, data_p->p2_body[index].y, TRON_PLAYER_2_COLOR);
    }
    Cube_Set_Pixel(data_p->p2_body[data_p->length-1].z, data_p->p2_body[data_p->length-1].x, data_p->p2_body[data_p->length-1].y, TRON_PLAYER_2_HEAD);
}

void Tron_Main(void) {
    // Main function, loops and delays while updating the frame every x milliseconds
    Tron_Update_Direction(0x04,0x04);
    Controller_Set_Leds(0x01,0x01);
    Delay_MS(2000);
    while (1) {
        Tron_Update_Frame();
        Delay_MS(data_p->delay);
    }
}

void Tron_Update_Direction(uint8_t p1, uint8_t p2) {
    // Determine the next direction for the trails based off the last button press
    if (p1) {
        TRON_P1_DIRECTION p1_dir;
        p1_dir.value = p1;
        data_p->p1_last_direction = p1_dir.value;
        TRON_POINT p1_point = data_p->p1_body[data_p->length - 1];
        if (p1_dir.up) {
            p1_point.z = (p1_point.z == CUBE_LAYER_COUNT - 1) ? 0 : p1_point.z + 1;
        } else if (p1_dir.down) {
            p1_point.z = (p1_point.z == 0) ? CUBE_LAYER_COUNT - 1 : p1_point.z - 1;
        } else if (p1_dir.forward) {
            p1_point.x = (p1_point.x == CUBE_ROW_COUNT - 1) ? 0 : p1_point.x + 1;
        } else if (p1_dir.right) {
            p1_point.y = (p1_point.y == CUBE_COLUMN_COUNT - 1) ? 0 : p1_point.y + 1;
        } else if (p1_dir.backward) {
            p1_point.x = (p1_point.x == 0) ? CUBE_ROW_COUNT - 1 : p1_point.x - 1;
        } else if (p1_dir.left) {
            p1_point.y = (p1_point.y== 0) ? CUBE_COLUMN_COUNT - 1 : p1_point.y - 1;
        }
        data_p->p1_direction = p1_point;
    }
    if (p2) {
        TRON_P2_DIRECTION p2_dir;
        p2_dir.value = p2;
        data_p->p2_last_direction = p2_dir.value;
        TRON_POINT p2_point = data_p->p2_body[data_p->length - 1];
        if (p2_dir.up) {
            p2_point.z = (p2_point.z == CUBE_LAYER_COUNT - 1) ? 0 : p2_point.z + 1;
        } else if (p2_dir.down) {
            p2_point.z = (p2_point.z == 0) ? CUBE_LAYER_COUNT - 1 : p2_point.z - 1;
        } else if (p2_dir.forward) {
            p2_point.x = (p2_point.x == CUBE_ROW_COUNT - 1) ? 0 : p2_point.x + 1;
        } else if (p2_dir.right) {
            p2_point.y = (p2_point.y == CUBE_COLUMN_COUNT - 1) ? 0 : p2_point.y + 1;
        } else if (p2_dir.backward) {
            p2_point.x = (p2_point.x == 0) ? CUBE_ROW_COUNT - 1 : p2_point.x - 1;
        } else if (p2_dir.left) {
            p2_point.y = (p2_point.y== 0) ? CUBE_COLUMN_COUNT - 1 : p2_point.y - 1;
        }
        data_p->p2_direction = p2_point;
    }
}

void Tron_Update_Frame(void) {
    // Check if there is a head-on collision
    if (data_p->p1_direction.x == data_p->p2_direction.x &&
            data_p->p1_direction.y == data_p->p2_direction.y &&
            data_p->p1_direction.z == data_p->p2_direction.z) {
        Cube_Set_Pixel(data_p->p1_direction.z, data_p->p1_direction.x, data_p->p1_direction.y, TRON_COLLISION);
        Delay_MS(3000);
        Animation_Cube_In_Out(200, TRON_COLLISION);
        Reset_Board(BOARD_MODE_IDLE);
    }

    // Check if the location that we are moving to is overlapping either trails
    uint32_t index, p1_collision = 0, p2_collision = 0;
    for (index = 0; index < data_p->length; index++) {
        if (data_p->p1_direction.x == data_p->p1_body[index].x &&
                data_p->p1_direction.y == data_p->p1_body[index].y &&
                data_p->p1_direction.z == data_p->p1_body[index].z) {
            p1_collision = 1;
        }
        if (data_p->p1_direction.x == data_p->p2_body[index].x &&
                data_p->p1_direction.y == data_p->p2_body[index].y &&
                data_p->p1_direction.z == data_p->p2_body[index].z) {
            p1_collision = 1;
        }
        if (data_p->p2_direction.x == data_p->p2_body[index].x &&
                data_p->p2_direction.y == data_p->p2_body[index].y &&
                data_p->p2_direction.z == data_p->p2_body[index].z) {
            p2_collision = 1;
        }
        if (data_p->p2_direction.x == data_p->p1_body[index].x &&
                data_p->p2_direction.y == data_p->p1_body[index].y &&
                data_p->p2_direction.z == data_p->p1_body[index].z) {
            p2_collision = 1;
        }
    }

    // Save the new head location of each trail
    data_p->length++;
    data_p->p1_body[data_p->length - 1] = data_p->p1_direction;
    data_p->p2_body[data_p->length - 1] = data_p->p2_direction;

    Cube_Clear();
    // Draw player 1 light trail
    for (index = 0; index < data_p->length - 1; index++) {
        Cube_Set_Pixel(data_p->p1_body[index].z, data_p->p1_body[index].x, data_p->p1_body[index].y, TRON_PLAYER_1_COLOR);
    }
    Cube_Set_Pixel(data_p->p1_body[data_p->length-1].z, data_p->p1_body[data_p->length-1].x, data_p->p1_body[data_p->length-1].y, TRON_PLAYER_1_HEAD);

    // Draw player 2 light trail
    for (index = 0; index < data_p->length - 1; index++) {
        Cube_Set_Pixel(data_p->p2_body[index].z, data_p->p2_body[index].x, data_p->p2_body[index].y, TRON_PLAYER_2_COLOR);
    }
    Cube_Set_Pixel(data_p->p2_body[data_p->length-1].z, data_p->p2_body[data_p->length-1].x, data_p->p2_body[data_p->length-1].y, TRON_PLAYER_2_HEAD);

    // Indicate the point of collision and reset to idle mode
    if (p1_collision || p2_collision) {
        uint32_t ind = data_p->length - 1;
        if (p1_collision)
            Cube_Set_Pixel(data_p->p1_body[ind].z, data_p->p1_body[ind].x, data_p->p1_body[ind].y, TRON_COLLISION);
        if (p2_collision)
            Cube_Set_Pixel(data_p->p2_body[ind].z, data_p->p2_body[ind].x, data_p->p2_body[ind].y, TRON_COLLISION);
        Delay_MS(3000);
        if (p1_collision && p2_collision)
            Animation_Cube_In_Out(200, TRON_COLLISION);
        else if (p1_collision)
            Animation_Cube_In_Out(200, TRON_PLAYER_2_HEAD);
        else if (p2_collision)
            Animation_Cube_In_Out(200, TRON_PLAYER_1_HEAD);
        Reset_Board(BOARD_MODE_IDLE);
    }

    // Determine the next direction to take
    Tron_Update_Direction(data_p->p1_last_direction, data_p->p2_last_direction);

    // Decrease the delay between frame updates by 5ms
    data_p->delay -= 5; 
}