LINUX.ORG.RU

Чем не нравится официальная документация? https://love2d.org/wiki/Main_Page

Если не понимаешь что там написано, то просто загугли отдельно непонятные слова.

anonymous
()

Первый раз вижу это.

  1. В love2d нет никаких классов и для обучения love они ненужны, в lua тоже их нет, но их можно сделать что и сделал rxi самым классическим способом.

  2. Ты видишь в примере require "classic" идёшь на

И там в README.md и в classic.lua текста описания и реализации представления класса в разы меньше чем в самих уроках по ссылка в шапке. Та 50 строчек кода и всё. Ознакомься непосредственно с предлагаемым к использованию модулем. Тогда всё остальное станет понятно.


Так или иначе что именно последнее не работает? Просто там всё размазано и последний пример он же кусок кода, это этап загрузки и инициализации всякого love.load, а не то что должно работать самостоятельно.

И что значит не работает? Если что-то не работает, значит ожидаемое поведение программы не то. Тогда что ожидалось? А предыдущее на этой странице работало значит. Самый последний пример (буквально кусок кода), ничего не делает, загрузка и выход

А так вики лове сломал РКН, самый лучший гайд по love это вики

Читать точечно по мере надобности =)

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от LINUX-ORG-RU

И что значит не работает?

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

vbcnthfkmnth123 ★★★★★
() автор топика
Ответ на: комментарий от vbcnthfkmnth123

Едрить, если бы я по такому учился тоже бы нихрена не понял :D А я по книгам и никогда не учился ахахаха

Короче, нет там не нужна глобальная переменная Shape, там нужно указать локальный модуль shape.lua в circle.lua так же как и в rectangle.lua, это там просто пропущено, и ещё в circle.lua пропущен возврат самого circle, когда ты делаешь глобальным shape всё работает, но ты делаешь костыль, который сводит всю чехорду что наворотили авторы на нет, объясняя типа классы, они там описывали как работать с модулями по факту, и накосячили. Повторюсь, объявление Shape глобальным это не решение. Щас не будет про classic.lua так он тут побоку, его отдельно гляди в README самого classic.lua лучше тем там тут не написать. Что происходит в примере.

Создаём main.lua в отличии от авторов которые зачем-то пропускают код, напишем всё полностью, в комментах опишу чего куда


local r1, r2; -- чтобы не срать в глобальное окружение 

function love.load() -- инициализируем
    Object = require "classic" -- единственное что нам нужно, если используется
                               -- глобально для всего, то это оно потребуется потом,
                               -- и как в оригинальном комментарии написано
                               -- We no longer need to require shape here.
                               -- так как мы используем Object для создания shape
                               -- только в самом shape.lua который нам нужен 
                               -- только внутри circle.lua и rectangle.lua

    -- мы их описали и собна получаем тут
    local Rectangle = require "rectangle"  
    local Circle    = require "circle"

    -- обрати внимание сюда 
    -- мы вызываем таблицу Rectangle как функцию в `classic.lua` можно
    -- увидеть что если таблица вызывается как функция то вызывается 
    -- ФУНКЦИЯ В ЭТОЙ ТАБЛИЦЕ под именем new
    r1 = Rectangle(100, 100, 200, 50)
    -- это можно записать как r1 = Rectangle:new(100,100,200,50) 
    -- если бы не пользовались `classic.lua` или не реализовывали вызов 
    -- таблицы как функции самостоятельно
    r2 = Circle(350, 80, 40)
end

function love.update(dt)
   r1:update(dt)
   r2:update(dt)
end

function love.draw()
   r1:draw()
   r2:draw()
end

shape.lua

--! file: shape.lua
local Shape = Object:extend() -- в main мы задали object как глобальный
                              -- и мы из object создали shape

function Shape:new(x, y)      -- в сам shape добавили его меременные 
    self.x = x
    self.y = y
    self.speed = 100
end

-- заметь что мы не описываем update в circle.lua и rectangle.lua
-- они получают это от `shape` 
function Shape:update(dt)     -- и функцию их обновления
    self.x = self.x + self.speed * dt
end

return Shape -- вернули

Теперь, мы создали объект shape из object, добавили в shape что-то своё и сохранили доставшееся из object. Тоесть расширили (extend) object в shape. Теперь у нас есть некая хрень shape которая имеет параметры x,y,speed + функции их начальной установки и функцию обновления плюс всё что было у object, а у него было extend и это значит что теперь и shape может делать extend что далее мы и делаем

--! file: rectangle.lua
--We could name our variable anything we want here, but it's nice to keep a consistent name.
local Shape = require "shape" -- тут мы изолируем shape от main, запирая его в этом модуле

--Let's also make rectangle local.
local Rectangle = Shape:extend() -- делаем из shape rectangle как сделали из object shape, и как и в shape.lua но уже тут, докидываем что-то своё в rectangle

-- если вызвать потом Rectangle(10,10,10,10)
-- то будет вызвано это как описано в `classic.lua`

function Rectangle:new(x, y, width, height) 
    Rectangle.super.new(self, x, y)
    self.width = width
    self.height = height
end

function Rectangle:draw()
    love.graphics.rectangle("line", self.x, self.y, self.width, self.height)
end

-- And then return it.
return Rectangle

Аналогичным образом поступаем и с circle.lua

--! file: circle.lua
local Shape = require "shape" -- они забыли дописать это
Circle = Shape:extend()

function Circle:new(x, y, radius)
    Circle.super.new(self, x, y) -- x, y лежат в "родительском" shape
     --A circle doesn't have a width or height. It has a radius.
    self.radius = radius -- а это личные вещи circle
end

function Circle:draw()
    love.graphics.circle("line", self.x, self.y, self.radius)
end

return Circle -- и забыли дописать это

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

Создаём глобальную таблицу Object у которой есть функция extend вызов этой функции вида Object:extend() можно записать и вот так Object.extend(Object)
Тем самым extend создаёт копию переданной ему таблицы

  • Создаём общий для всех Object, глобальный видно везде
  • Одну из копий Object называем shape и добавляем туда общие вещи
    • позицию
    • скорость
    • плюс сохраняем возможность расширяться дальше
  • Теперь берём общую копию shape делаем её две копии rectangle + circle
    • в каждую из них добавляем свои специфичные вещи

Ещё момент, по поводу вызова Rectangle(blabla)

-- rectangle это таблица
local r = Rectangle(10,10,10,10) 
-- вызванная как функция она дёргает описанное в `rectangle.lua`
function Rectangle:new(x, y, width, height)
    Rectangle.super.new(self, x, y)
    self.width = width
    self.height = height
end
-- но тут нет возврата. Как так, а дело в том что оно дёргает `new` вот так, как в `classic.lua`
function Object:__call(...)
  local obj = setmetatable({}, self)
  obj:new(...) -- вот он наш описанный в `rectangle.lua` Rectangle:new
  return obj -- а вот возврат
end
--итоговый `r` как и те `r1` `r2` если ты посмотришь на них вот так
  for name,val in pairs(r2) do
      print(name,val)
  end
-- не имеют никаких `update`/`draw` 
-- но эти функции тоже вызываются
-- тут надо снова нырнуть в `classic.lua`
  cls.__index = cls
-- __index задаётся для случая когда идёт попытка обращения к несуществующему ключу
-- в `r1` нет `update` но в его метатаблице заданной ему ранее на этот случай 
-- уже задан `__index` содержащий `update` доставшийся от `shape`

Короче, классы, наследования, это всё здорово, но их можно сделать разными способами, я бы не сказал что они прям что-то решают, ну типа прикольна, но сходу можно сильно запутаться если не держать в голове как они именно тут реализованы. Например тебе по логике захочется сделать снимок состояния r1 типа вот так r3 = r1:extend() но уже не получится, это надо доделывать в classic.lua хотя такое назвать уже лучше clone или copy но не суть.

Расписал как мог. Может где ошибся. Но по началу лучше ну нахер все эти классы и так далее, у тебя на руках есть мощная система таблиц, а уж метатаблицы ты можешь сам точечно использовать и явным образом. Только там где это надо. Сами по себе таблицы можно рассматривать как объекты если удобно.

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от vbcnthfkmnth123

Добавлю ещё, я выше писал нафиг не нужны классы, система вермишели наследования от объекта к объекту… На это не обращай сильно внимания, так как я неосилятор, и избегаю такого так как меня дико путает когда это расширено от этого, а это зависит от вон того и если в предке до пятого колена изменить то изменится у всех, а если раньше то только у последнего. Лично мои бзики и закидоны. Так как сильных преимуществ нет, ограничения есть, делается всё неявно, зависит от конечной реализации эмуляции классов и наследования, заставляет использовать метатаблицы неявно везде где надо и где не надо, с учётом того что это потребляет значительно больше ресурсов чем линейный код, особенно в местах которые вызываются часто например update.

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

  • self
  • metatable

Всё остальное следствие того как они работают. С учётом что они могут, а что нет.

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от vbcnthfkmnth123

И ещё я сам ошибся

local Shape = require "shape" -- они забыли дописать это
-Circle = Shape:extend()
+local Circle = Shape:extend()

Если делать то одинаково, нам не надо Circle глобальный создавать.
Авторы там мудрили смотрите мол Rectangle так, а Circle сяк и именно по этому в конце небыло return у циркля.
Ну да так можно сделать, но не нужно, вернее если можно то для всего, а не запутывая это мол получаем из возврата через явное присвоение, а это молучаем по факту подгрузки модуля в глобальной области для всей прпограммы

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 3)
  • Markdown
Пустая строка (два раза Enter) начинает новый абзац. Знак '>' в начале абзаца выделяет абзац курсивом цитирования.
Внимание: прочитайте описание разметки Markdown.
Используйте Ctrl-Enter для размещения комментария