СоХабр закрыт.

С 13.05.2019 изменения постов больше не отслеживаются, и новые посты не сохраняются.

H Моя первая игра на Swift под iOS в черновиках

В этой статье мне хотелось бы поделиться опытом, который я получил во время разработки моей первой игры под iOS. После анонса языка Swift идея разработки под iOS не переставала покидать моя голову. Так как я уже достаточно давно на тот момент работал веб-разработчиком, а Swift оказался очень похож на Javascript, я решил приступить к осуществелению своей затеи.



И вот, имея в наличии достаточно времени, и являясь поклонником казуальных игр, я решил сделать свою игру в этом жанре. Прототип был быстро cделан на Javascript c использованием либы Raphaeljs для комфортной работы с графикой.

Идея и правила были придуманы буквально на колене и заключаются в следующем:
  • Каждый раунд игроку даются 3 полимино
  • Игрок должен расположить их на поле, стремясь к максимальной упорядоченности, заключающейся в отстутсвии гэпов между фигурами
  • При сборе линии, неважно горизонтальной или вертикальной, игрок получает определённое количество очков, умножающееся на коэффициент комбо
  • Игра завершается в тот момент, когда из фигур, представленных на выбор, ни одна не может быть расположена на игровом поле


Реализация на JS заняла около двух дней. Еще до разработки я планировал, что с помощью IONIC или Phonegap легко все перекомпилю в приложение для IOS, но, как я и предполагал, получилось очень плохо, так как код на JS, вставленный в WebView, работал с лагами и тормозами, и я решил, в итоге, все переделать на Swift. И понеслось…

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

алгоритм
func tryFigureOnMap(figure : Figure) -> Bool {
    let rect_map = figures_for_test_inited.maps[figure.type]!
    let except_first_element_width = figure.w
    let start_width_offset = figure.start_w_offset == nil ? 0 : figure.start_w_offset
    let except_first_element_height = figure.h
    var rect_figures = Array<Array<Int»()
    var rect_offsets = Array<Array<Int»()
    var num = Int()
    var direction : Bool = except_first_element_width > except_first_element_height

    for var c = 0; c < map_size; c++ {
        for var r = 0; r < map_size; r++ {
            num = c * map_size + r

            if rectanglesArray[num].type == "default" {
                var counter = 0
                var array_helpers = Array<Int>()

                if r < map_size - except_first_element_width && c < map_size - except_first_element_height && r >= start_width_offset {
                    for (index, i) in enumerate(rect_map) {

                        let need_num = num + i
                        if let q = find(clearNumbers, need_num) {
                            counter++
                            array_helpers.append(need_num)
                        } else {
                            break
                        }
                    }
                    if counter == rect_map.count {
                        return true
                    }
                }
            }
        }
    }
    return false
}


Проблема заключалась в том, что для некоторых фигур их началом считался верхний правый угол, тогда как для остальных фигур отправной точкой считался левый верхний угол. Для решения этой проблемы в мапу этой фигуры, помимо конечного отступа, добавлялся ещё и начальный отступ, обозначающий, что начало этой фигуры учитывало её сдвиг.

Пример:



Для фигуры пентамино «L» (на картинке голубая) начальной точкой считается левый верхний угол, соответсвенно её начальный отступ равен нулю, а конечный равен 2, а для пентамино «обратная L» начальный отступ равен 2, а начальный — нулю, соответсвенно, её обход начинается с правого верхнего угла, а заканчивается левым.

Мапы фигур, использующиеся для проверки:

maps["L_inv"] = [0, 10, 20, 19, 18]
maps["L"] = [0, 10, 20, 21, 22] 


А сама мапа фигуры, использовавшаяся для отрисовки, выглядела так:

self.maps.append([
"map" : [
[ "x" : 0.5, "y" : -1.5 ],
[ "x" : 0.5, "y" : -0.5 ],
[ "x" : -1.5, "y" : 0.5], [ "x" : -0.5, "y" : 0.5], [ "x" : 0.5, "y" : 0.5]
],
"color" : UIColor(rgb: 0x41CE57),
"w" : 0,
"h" : 2,
"start_w" : 2,
"type" : "bigL_inv"
])


Саму игру можно скачать в appstore, она бесплатная.

Игра.

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

комментарии (1)

0
Suvitruf ,  
Я пиарюсь.