LinkedIn YouTube Facebook
Szukaj

Newsletter

Proszę czekać.

Dziękujemy za zgłoszenie!

Wstecz
Artykuły

Implementacja dotykowej wersji „Snake” na STM32F4DISCOVERY

Ekran wstępnie podzielony został na dwie części (połówkę górną wraz belką nagłówkową i połówkę dolną). Pozycja lewa górna odpowiada współrzędnym x=0 i y=0, gdzie x to krawędź pozioma, a y to krawędź pionowa.

Dla połówki górnej pozycje dla x<y to pole czerwone (ruch w lewo), pozycje xmax–x<y to pole zielone (ruch w prawo), a pozostałe pozycje to pole niebieskie (ruch do góry).

Analogicznie jest dla połówki dolnej: x<ymax–y to pole czerwone (ruch w lewo), xmax–x<ymax–y to pole zielone (ruch w prawo), a pozostałe pozycje to pole czarne (ruch do dołu).

Na podstawie wyznaczonego kierunku ruchu następuje wyznaczenie nowej pozycji głowy węża, przy czym jeśli nowa pozycja dotyka krawędzi ekranu następuje zakończenie gry (listing 4).

 

List. 4.

    switch (direction)
    {
    case left:
        if (MOVE_MARGIN >= g_snake[0].x)
            ret_val = RET_GAME_OVER;

        g_snake[0].x -= SNAKE_STEP;
        break;
    case right:
        if((DISP_HOR_RESOLUTION - MOVE_MARGIN) <= g_snake[0].x)
            ret_val = RET_GAME_OVER;

        g_snake[0].x += SNAKE_STEP;
        break;
    case up:
        if ((MOVE_MARGIN + HEADER_SIZE) >= g_snake[0].y)
            ret_val = RET_GAME_OVER;

        g_snake[0].y -= SNAKE_STEP;
        break;
    case down:
        if ((DISP_VER_RESOLUTION - MOVE_MARGIN) <= g_snake[0].y)
            ret_val = RET_GAME_OVER;

        g_snake[0].y += SNAKE_STEP;
        break;
    }

Współrzędne poszczególnych elementów węża umieszczone są w tablicy, a jego ruch polega na narysowaniu głowy na nowej pozycji i usunięciu ostatniego fragmentu ogona z jednoczesnym przesunięciem wszystkich pozycji w tablicy współrzędnych (listing 5).

 

List. 5.

    // remove last part of snake
    LCD_SetTextColor(BACKGROUND_COLOR);
    LCD_DrawFullRectFill(g_snake[partsCount-1].x - 5, g_snake[partsCount-1].y - 5, 11, 11, true);

    for (part = partsCount-1; part > 0; part--)
    {
        g_snake[part].x = g_snake[part-1].x;
        g_snake[part].y = g_snake[part-1].y;
    }

    // print head on new position
    LCD_SetColors(SNAKE_COLOR_BODY, SNAKE_COLOR_HEAD);
    LCD_DrawFullCircle(g_snake[0].x, g_snake[0].y, 5);
    LCD_DrawFullCircleFill(g_snake[1].x, g_snake[1].y, 5, true);

Jeśli nowa pozycja głowy węża pokrywa się z pozycją celu, to następuje narysowanie nowej pozycji celu, zwiększenie liczby punktów, wzrost węża oraz przyspieszenie jego ruchu. Zwiększenie prędkości węża następuje co określoną (SPEED_INCREASE_STEPS_CNT) liczbę punktów (listing 6).

 

List. 6.

    if ( (target.x == g_snake[0].x)
       &&(target.y == g_snake[0].y) )
    {
        target.new = true;
        g_points++;
        snakeGrow();
        if (0 == --speedIncreaseCnt)
        {
            speedIncreaseCnt = SPEED_INCREASE_STEPS_CNT;
            g_snakeSpeed -= g_snakeSpeed>>2;
            if (SPEED_LIMIT > g_snakeSpeed)
                g_snakeSpeed = SPEED_LIMIT;
        }
    }

Nowa pozycja celu powinna być wyznaczana w losowy sposób. Mikrokontrolery z rodziny STM32F4 mają wbudowany sprzętowy generator liczb losowych. Jednak w tym przypadku stopień losowości nie musi być wysoki i dlatego w tym celu wykorzystany został licznik zegarowy. Moment „trafienia” celu raczej nie będzie się powtarzał, dzięki czemu uzyskamy wystarczającą pseudolosowość. Po wyznaczeniu nowego punktu trzeba sprawdzić, czy jego pozycja jest poprawna i jeśli wszystko się zgadza można narysować „jabłko” w nowych współrzędnych (listing 7).

 

List. 7.

    if (target.new)
    {
        target.x = (getSysTick()%TARGET_X_RATIO + 1) * 10 + 5;
        target.y = (getSysTick()%TARGET_Y_RATIO + 1) * 10 + 5 + HEADER_SIZE;
        for (part = 0; part < g_snakeSize; part++)
        {
            if ((target.x == g_snake[part].x) &&
                (target.y == g_snake[part].y))
            {
            	   // target cannot be on the snake, generate the new one
                return true;
            }
        }
        LCD_SetColors(TARGET_COLOR, BACKGROUND_COLOR);
        LCD_DrawFullCircleFill(target.x, target.y, 3, true);
        target.new = false;
    }

Prezentowany projekt w minimalnym stopniu wykorzystuje możliwości zestawu STM32F4DISCOVERY. Wykorzystując elementy peryferyjne dostępne na płytce zestawu (jak akcelerometr), można urozmaicić grę o dodatkowy sposób sterowania za pomocą ruchu (przechyłu) płytki. Idąc dalej, czujnik dźwięku z wbudowanym mikrofonem można wykorzystać do głosowego sterowania wężem dodając prosty moduł rozpoznawania mowy. Wbudowany przetwornik audio można wykorzystać do urozmaicenia gry dźwiękami.