Движение врагов

Программирование игры на Ардуино: 2-пришельцы

Ну вот, теперь у нас есть вражеские юниты, которые тоже должны как-то двигаться. По статичным врагам будет слишком легко попадать. Пусть все 24 врага медленно двигаются сначала до правого края игрового поля, а затем обратно.

Наша программа постоянно усложняется. Чтобы код не превратился в помойку, в которой сложно будет разобраться, выведем сложные операции из цикла loop в отдельные функции. Так мы сделаем программу более понятной.

#include <Adafruit_SSD1306.h>

#define WIDTH 128
#define HEIGHT 64
#define UNIT_WIDTH 5
#define UNIT_HEIGHT 4
#define X 0
#define Y 1
#define CTRL_TO 50
// ENEMY_TO - это время, через которое враги совершают очередное смещение
#define ENEMY_TO 1000

byte pinLeft = A0;
byte pinRight = A1;

byte player_coords[2];
byte enemy_coords[24][2];
// добавим переменную enemy_next для таймера движения врагов
unsigned long t, ctrl_next, enemy_next;

// нам нужно постоянно помнить на сколько пикселей вбок сместились враги
// и в какую сторону они сейчас смещаются
byte enemy_drift_x = 0;
int enemy_drift_dir = 1;

// спрайт игрока
byte player_sprite[UNIT_WIDTH*UNIT_HEIGHT] = {
    0,0,1,0,0,
    0,1,1,1,0,
    1,1,0,1,1,
    1,1,0,1,1
};

// спрайт врагов
byte enemy_sprite[UNIT_WIDTH*UNIT_HEIGHT] = {
    1,0,1,0,1,
    0,1,1,1,0,
    0,1,0,1,0,
    1,0,1,0,1
};

Adafruit_SSD1306 display(4);

// первая функция enemyMove отвечает за смещение врагов
void enemyMove(){
    if(enemy_drift_dir > 0 && enemy_drift_x < 50)
        enemy_drift_x += 1;  
    else if(enemy_drift_dir < 0 && enemy_drift_x > 5)
        enemy_drift_x -= 1;
    else
        enemy_drift_dir = -1*enemy_drift_dir;
}

// здесь мы опрашиваем тактовые кнопки и двигаем игрока
void handleControls(){
    if( digitalRead(pinLeft) && player_coords[X]>0 )
        player_coords[X] -= 1;
    else if( digitalRead(pinRight) && player_coords[X]<WIDTH-1 )
        player_coords[X] += 1;
}

// отдельная функция для отрисовки игрока
void drawPlayer(){
    for(byte px=0; px<UNIT_WIDTH; px++)
        for(byte py=0; py<UNIT_HEIGHT; py++)
            display.drawPixel(player_coords[X]+px, player_coords[Y]+py, player_sprite[px+py*5]);
}

// отдельная функция для отрисовки врагов
void drawEnemies(){
    for(byte e=0; e<24; e++)
        for(byte px=0; px<UNIT_WIDTH; px++)
            for(byte py=0; py<UNIT_HEIGHT; py++)
                display.drawPixel(enemy_coords[e][X]+px+enemy_drift_x, enemy_coords[e][Y]+py, enemy_sprite[px+py*5]);
}

void setup() {
    pinMode( pinLeft, INPUT );
    pinMode( pinRight, INPUT );

    // начальные координаты игрока
    player_coords[X] = WIDTH/2-UNIT_WIDTH/2;
    player_coords[Y] = HEIGHT-1-UNIT_HEIGHT;

    // начальные координаты врагов
    for( byte x=0; x<8; x++){ // в ряду 8 врагов
        for( byte y=0; y<3; y++){ // всего 3 ряда врагов
            byte idx = x+y*8;
            enemy_coords[idx][X] = 5 + x*(5+5);
            enemy_coords[idx][Y] = 5 + y*(3+5);
        }
    }

    ctrl_next = millis() + CTRL_TO;

    // инициализация дисплея
    display.begin(SSD1306_SWITCHCAPVCC, 0x3D);
    display.clearDisplay();
}

// очень компактный суперцикл, в котором нет ничего лишнего
void loop() {
    unsigned long t = millis();
    if( t > ctrl_next ){
        ctrl_next = t + CTRL_TO;
        
        handleControls(); // обработка нажатий кнопок

        display.clearDisplay(); // очистка фрейма
        drawPlayer(); // отрисовка игрока на фрейме
        drawEnemies(); // отрисовка врагов на фрейме
        display.display(); // вывод фрейма на дисплей
    }
    // добавляем обработку таймера для движения врагов
    if( t > enemy_next ){
        enemy_next = t + ENEMY_TO;
        enemyMove();
    }
}

В результате мы должны наблюдать медленный дрейф армады врагов сначала до края игрового поля вправо, затем влево.

На следующем уроке научим корабль игрока стрелять во врагов ракетами и обрабатывать попадания. Зададим им!

Все уроки на эту тему:


Изменено:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.