Game Dev: Очумелые ручки. ["крестики-нолики"] (LOVE. Lua)

» Раздел: Прочее
» Автор: DasBro

Всех приветствую! Сегодня мы начнём заделывать игру "крестики-нолики" на Lua, используя при этом такую библиотеку как LOVE. Первым делом необходимо создать два стандартных скрипта main.lua и conf.lua.
Запихнём их в отдельную папку, где у нас и будут хранится все скрипты игры. Далее для наглядности вызова функций из других скриптов, я создал скрипт figuresCreate.lua.
Теперь перейдём к рассмотрению и написания кода. Собственно в conf.lua мы вставляем код, который нам дают в LOVE Wiki. Вот такой вот кодец:
function love.conf(t)
    t.identity = nil                    
    t.version = "0.10.0"            
    t.console = false                 
    t.accelerometerjoystick = true     
    t.gammacorrect = false             
 
    t.window.title = "Крестики-Нолики"         
    t.window.icon = nil             
    t.window.width = 800               
    t.window.height = 600              
    t.window.borderless = false        
    t.window.resizable = false          
    t.window.minwidth = 1              
    t.window.minheight = 1            
    t.window.fullscreen = true       
    t.window.fullscreentype = "desktop"
    t.window.vsync = false               
    t.window.msaa = 0                  
    t.window.display = 1               
    t.window.highdpi = false            
    t.window.x = nil                 
    t.window.y = nil                    
 
    t.modules.audio = true           
    t.modules.event = true             
    t.modules.graphics = true           
    t.modules.image = true            
    t.modules.joystick = true          
    t.modules.keyboard = true           
    t.modules.math = true              
    t.modules.mouse = true            
    t.modules.physics = true           
    t.modules.sound = true              
    t.modules.system = true             
    t.modules.timer = true             
    t.modules.touch = true             
    t.modules.video = true             
    t.modules.window = true            
    t.modules.thread = true           
end
В conf.lua Нам необходимо изменить лишь несколько строк. Во-первых находим вызов полноэкранного режима t.fullscreen. Меняем значение на true для удобства. А также меняем заголовок игры t.title на желаемый. Я выбрал "Крестики-Нолики". Не правда ли оригинально, а?
Далее пропишем несколько функций в скрипте figuresCreate.lua.
А именно вот такие:

function createSquare(typeShape,x,y,width,height,colorR,colorG,colorB,colorA)

    love.graphics.setColor(colorR,colorG,colorB,colorA);
    love.graphics.rectangle(typeShape,x,y,width,height);
    
end

function createCross(xA,yA,xB,yB,colorR,colorG,colorB,colorA)

    love.graphics.setColor(colorR,colorG,colorB,colorA);
    love.graphics.line(xA,yA,xB,yB);
    love.graphics.line(xB,yA,xA,yB);
    
end
Разберём код по-подробнее. У нас есть три функции, которые имеют достаточно много аргументов.
Итак, я создал функцию createSquare с параметрами:
  1. Тип квадрата (обводка или заливка).
  2. Позицию (x,y).
  3. Длину и Ширину (width, height).
  4. Значение цветовых каналов RGBA (colorR,colorG,colorB,colorA)
Далее можно видеть ещё функцию createCross, которая будет рисовать крестик внутри квадрата.
Там практически схожие параметры.
Теперь рассмотрим самый главный скрипт main.lua
Вот исходный код:

dofile("figuresCreate.lua");

centerX = love.graphics.getWidth() / 2.7;
centerY = love.graphics.getHeight() / 3;

randomColorChannel = {}

widthBox = 100;
heightBox = 100;

offsetX = -widthBox;



function love.load()
     for countBoxesX = 0,10 do
		 randomColor(tostring(countBoxesX));   
		countBoxesX = countBoxesX + 1;
		offsetX = 0  + widthBox;   
     end
 end

function randomColor(id)
    
    randomColorChannel["R" .. id] = math.random(255);
    randomColorChannel["G" .. id] = math.random(255);
    randomColorChannel["B" .. id] = math.random(255);
end
 

function love.update(frame)

    
end

function love.keypressed(keyCode)
    
    if keyCode == "escape" then
        
        love.window.close();
        end 
    
    
end




function love.draw()
    

createGrid();   
createCross(centerX + (widthBox / 4),centerY + (widthBox / 4),centerX + 75, centerY + 75,255,255,255,255);
       
end

function createGrid(offsetY)
    
   offsetY = widthBox;
    
-- Первый Ряд
createSquare("line",centerX ,centerY,widthBox,heightBox, randomColorChannel["R0"],randomColorChannel["G0"],randomColorChannel["B0&qu​ot;],255);
    
    createSquare("line",centerX + offsetX,centerY,widthBox,heightBox, randomColorChannel["R1"],randomColorChannel["G1"],randomColorChannel["B1&qu​ot;],255);
    
   createSquare("line",centerX + (offsetX * 2),centerY,widthBox,heightBox, randomColorChannel["R2"],randomColorChannel["G2"],randomColorChannel["B2&qu​ot;],255);
    
    -- Второй Ряд
    createSquare("line",centerX ,centerY + offsetY ,widthBox,heightBox, randomColorChannel["R4"],randomColorChannel["G4"],randomColorChannel["B4&qu​ot;],255);
    
    createSquare("line",centerX + offsetX,centerY + offsetY,widthBox,heightBox, randomColorChannel["R5"],randomColorChannel["G5"],randomColorChannel["B5&qu​ot;],255);
    
   createSquare("line",centerX + (offsetX * 2),centerY + offsetY,widthBox,heightBox, randomColorChannel["R6"],randomColorChannel["G6"],randomColorChannel["B6&qu​ot;],255);
    
    
    
    -- Третий Ряд
    local offset = offsetY + widthBox;    
    createSquare("line",centerX ,centerY + offset ,widthBox,heightBox, randomColorChannel["R7"],randomColorChannel["G7"],randomColorChannel["B7&qu​ot;],255);
    
    createSquare("line",centerX + offsetX,centerY + offset,widthBox,heightBox, randomColorChannel["R8"],randomColorChannel["G8"],randomColorChannel["B8&qu​ot;],255);
    
   createSquare("line",centerX + (offsetX * 2),centerY + offset,widthBox,heightBox, randomColorChannel["R9"],randomColorChannel["G9"],randomColorChannel["B9&qu​ot;],255);
        
end
Теперь примемся к рассмотрению этого огромного кода.
В начале я вызываю такую крутую штуку как dofile, которая позволяет обращаться к другому скрипту.
В ней я прописываю имя нашего скрипта и его расширение.
После этого я создаю две переменные centerX и centerY, чтобы создать наше игровое поле в центре экрана.
Далее я создаю таблицу randomColorChannel без элементов. Я собираюсь для каждой клетки игрового поля генерировать разный цвет. Собственно наша таблица позволит хранить каждый сгенерированный цвет в n-ом элементе.
Далее я создаю две переменные widthBox и heightBox, которые служат для указания размеров клетки игрового поля.
Далее я создал скажем так странную переменную offsetX . В ней я храню отрицательное значение длины клетки. Для чего? Я это делаю из-за цикла, в котором у нас offsetX прибавляется. Скажем так, до написания этой статьи, я немного сделал криво, поэтому сейчас объясню, как сделать красиво. Вот так:
offsetX = 0;

function love.load()
	for countBoxesX = 0,10 do
		randomColor(tostring(countBoxesX));   
		offsetX = 0  + widthBox;   
		countBoxesX = countBoxesX + 1;
	end
end
Собственно сейчас всё должно быть так, как и у меня. Сейчас рассмотрим этот код.
Итак, рассмотрим функцию love.load. Здесь мы создаём цикл, который будет генерить наш цвет для каждой клетки. Там происходит вызов функции, которую мы ещё не рассмотрели, поэтому мы ещё вернёмся к этому. Далее мы назначаем расстояние между клетками и инкрементируем наше число из цикла, чтобы цикл дошёл до 10.
Далее как раз-то таки функция randomColor. У неё есть параметр id. Он нужен для каждой клетки.
В функции мы назначаем таблице элементы и содержимое элементов. Здесь: ["R" .. id] мы даём название цветового канала R (Red) и приписываем id'шник. В общем в итоге получится название элементов такого типа:
R0 R1 R2
G0 G1 G2
B0 B1 B2
Собственно это три цвета для трёх клеток. Генереруем цвет с помощью math.random, где в параметре я указал 255 максимальное, но желательно указать ещё и минимальное 0, чтобы не было опасений за генерацию отрицательных чисел.
После этого у меня записана функция love.update, но в этой части она пока не используется.
Используется функция love.keypressed, с параметром нажатой клавиши. В этой функции я сделал проверку на нажатие кнопки Escape, после чего наша игра закроется.
Хочу заметить что выход из игры был реализован для быстрого закрытия окна, т.к. игра открывается в полноэкранном режиме. Ты же можешь сделать игровую паузу.
Предпоследняя функция love.draw вызывает два метода. createGrid() и createCross.
Сначала рассмотрим createCross. Этот метод я вызываю для демонстрации отрисовки крестика внутри клетки. Конечно, в других частях будет записано иначе. Также, прошу заметить этой функции у нас нет в файле main.lua. createCross хранится в figuresCreate.lua и вызывается Прямым путём.
В этом методе я заполняю параметры, которые мы описали в создании функции. Кстати, крестик я отрисовываю при помощи двух линий.
  1. Позиция первой линии по X и Y- это центр, делённый на 4. Почему так? Потому что первая клетка рисуется в позиции centerX и centerY, если мы взяли бы те же значения, первая линия начала рисоваться бы ровно в углу квадрата, что нам не нужно.
  1. Позиция второй линии. В самой функции createCross я меняю местами параметры в методе love.graphics.line, чтобы создать "зеркальное" отражение первой линии, таким образом получая крест.
  1. Потом я задаю значения для RGBA каналов. В данном случае я отрисовал в белом цвете.
Теперь последняя функция createGrid. Она рисует все 9 клеток. В ней есть параметр offsetY, который служит для отступа нижних рядов. Здесь я вызвал 9 раз метод createSquare и заполнил их параметрами.
Думаю что описывать всю последнюю функцию не стоит, она слишком огромная получилась.Но если хотите могу описать, но уже в следующей части.
На этом всё, вот результат работы:
Здесь я отключил полноэкранный режим, так как кнопка быстрого создания скриншота у меня не работает. Пришлось делать скриншот через одну программку.
P.S. Весь код был написан лично мной, а значит все претензии ко мне..
В следующей части мы сделаем главное меню, а также расстановку крестиков и ноликов.

Просмотров: 1 862

ScorpioT1000 #1 - 3 года назад 0
Неплохо, синтаксис бы еще поправить
Ethernet #2 - 3 года назад (отредактировано ) 0
А пример с работай со спрайтами будет? Например, есть ленточный спрайт с анимацией персонажа, как реализовывается прорисовка?
DasBro #3 - 3 года назад 0
ScorpioT1000, Обязательно
Ethernet, Всё будет
noomnau #4 - 3 года назад 0
Спасибо! Поддерживаю идею с простыми играми для изучения движка!
LeikyS #5 - 3 года назад 0
DasBro:
ScorpioT1000, Обязательно
Ethernet, Всё будет
Скажу честно..Я уже устал ждать следующую часть!
Ethernet #6 - 3 года назад 0
LeikyS:
DasBro:
ScorpioT1000, Обязательно
Ethernet, Всё будет
Скажу честно..Я уже устал ждать следующую часть!
А что-нибудь сам пробовал написать?)
LeikyS #7 - 3 года назад 0
Да пробовал. Результат 50/50 приходилось заглядывать в статьи :)
LeikyS #8 - 2 года назад 0
И где продолжение?