Ошибка при попытке нарисовать платформы в Lua / Love2D

#lua #game-development #love2d

#lua #разработка игры #love2d

Вопрос:

Новичок в Lua / Game dev в целом. Я пытаюсь написать код для рисования фона моей игры. У меня есть четыре разных таблицы спрайтов для вещей, связанных с настройками:

  • Background — который содержит нарисованное «фоновое изображение» игры
  • Платформы — которые содержат платформенные спрайты игры
  • objectsBig — которые содержат относительно большие нарисованные объекты на заднем плане (например, камни, морские водоросли и т.д.)
  • Объекты Small — которые содержат нарисованные объекты относительно меньшего размера (камни меньшего размера, растения и т.д.)

Я создал функцию, вызываемую generateQuads() из моего Util.lua файла, которая, получив таблицу спрайтов, разбивает ее на разные спрайты в таблице спрайтов и возвращает эти спрайты. Это выглядит следующим образом:

 -- Function to generate quads/cut the spritesheet
function generateQuads(atlas, tileWidth, tileHeight)
    local sheetWidth = atlas:getWidth() / tileWidth
    local sheetHeight = atlas:getHeight() / tileHeight
local sheetCounter = 1
local quads = {}

-- for every line of the sprite sheet
for y = 0, sheetHeight - 1 do
    -- for every piece in the width
    for x = 0, sheetWidth - 1 do
        -- quads generated will be the ones specified by tileWidth and tileHeight
        quads[sheetCounter] = love.graphics.newQuad(x * tileWidth, y * tileHeight, tileWidth, 
            tileHeight, atlas:getDimensions())
        sheetCounter = sheetCounter   1
    end
end

return quads

end
  

У меня также есть класс с именем Map , который предназначен для хранения информации для карты. Ниже приведены функции в нем:

ФУНКЦИЯ ДЛЯ НАСТРОЙКИ КЛАССА

 function Map:init()
    -- Load the background sprite into variable
    -- Each is 500x500, total is 1500x500
    self.background = love.graphics.newImage('Graphics/platform/background/full.png')

-- Load all the ground platforms into variable
-- Each is 60x30, total is 240x30
self.platforms = love.graphics.newImage('Graphics/platform/ground/all.png')

-- Load all the bigger misc objects into variable
-- Each is 15x20, total is 15x120
self.objectsBig = love.graphics.newImage('Graphics/platform/objects/15x20/all.png')

-- Load all the smaller misc objects into variable
-- Each is 15x15, total is 60x15
self.objectsSmall = love.graphics.newImage('Graphics/platform/objects/15x15/all.png')

-- Setting the size for each of the variables IN PIXELS
self.backgroundWidth = 500
self.backgroundHeight = 1500

self.platformWidth = 60
self.platformHeight = 30

self.objectsBigWidth = 15
self.objectsBigHeight = 20

self.objectsSmallWidth = 15
self.objectsSmallHeight = 15

-- Setting the map size IN TILES
-- EXPERIMENTAL, CHECK AGAIN
self.mapWidth = 432
self.mapHeight = 243

-- Setting the width of the map IN PIXELS (in relation to platforms)
self.mapWidthPixels = self.backgroundWidth
self.mapHeightPixels = self.backgroundHeight

-- Storing our map features
self.tiles = {}

-- Storing the camera points, starting from the bottom
-- The 243 is the VIRTUAL_HEIGHT, which we needed to subtract to account for the
-- offset of the screen
self.camX = 0
self.camY = self.backgroundHeight - 243

-- Cutting each of the spritesheets
self.backgroundSprite = generateQuads(self.background, self.backgroundWidth, self.backgroundHeight)
self.platformSprite = generateQuads(self.platforms, self.platformWidth, self.platformHeight)
self.objectsBigSprite = generateQuads(self.objectsBig, self.objectsBigWidth, self.objectsBigHeight)
self.objectsSmallSprite = generateQuads(self.objectsSmall, self.objectsSmallWidth, self.objectsSmallHeight)

-- 'Setting' the tiles for the map to be background 
for y = 1, self.mapHeight do
    for x = 1, self.mapWidth do
        self:setTile(x, y, BACKGROUND)
    end
end

-- 'Setting' the platform tiles for where we start
for x = 1, self.mapWidth do
    self:setTile(x, self.mapHeight - 303, GROUND_MIDDLE)
end
end
  

ФУНКЦИЯ ДЛЯ «УСТАНОВКИ», ГДЕ В КООРДИНАТАХ X, Y ДОЛЖНЫ НАХОДИТЬСЯ ПЛИТКИ

 function Map:setTile(x, y, tile)
    -- The table 'tiles' is going to store what tile should be in what x and y position
    -- subtracting y by 1 so that it's 0 indexed, not 1 indexed
    self.tiles[(y - 1) * self.mapWidth   x] = tile
end
  

FUNCTION TO RETURN WHAT TILE IS IN THE X, Y COORDINATE

 function Map:getTile(x, y, tile)
    -- This function is going to tell us what tile is set at this x and y position
    return self.tiles[(y - 1) * self.mapWidth   x]
end
  

FUNCTION TO UPDATE

 function Map:update(dt)
    -- Moving the camera depending on the key being pressed
    if love.keyboard.isDown('w') then
        -- up movement, clamped between 0 and the other
        self.camY = math.max(0, math.floor(self.camY - SCROLL_SPEED * dt))
    elseif love.keyboard.isDown('a') then
        -- left movement
        self.camX = math.max(0, math.floor(self.camX - SCROLL_SPEED * dt))
    elseif love.keyboard.isDown('s') then
        -- down movement, subtracting VIRTUAL_HEIGHT to account for the screen offset
        self.camY = math.min(self.backgroundHeight - VIRTUAL_HEIGHT, math.floor(self.camY   SCROLL_SPEED * dt))
    elseif love.keyboard.isDown('d') then
        -- right movement
        self.camX = math.min(self.backgroundWidth - VIRTUAL_WIDTH, math.floor(self.camX   SCROLL_SPEED * dt))
    end
end
  

FUNCTION TO RENDER

 function Map:render()
    for y = 1, self.mapHeight do
        for x = 1, self.mapWidth do
            -- Drawing the background first
            love.graphics.draw(self.background, self.backgroundSprite[self:getTile(x, y)],
                (x - 1) * self.backgroundWidth, (y - 1) * self.backgroundHeight)
            love.graphics.draw(self.platform, self.platformSprite[self:getTile(x, y)],
                (x - 1) * self.platformWidth, (y - 1) * self.platformHeight)
        end
    end
end
  

Что я пытаюсь сделать, так это объединить каждую таблицу спрайтов и установить фоновые и нижние плитки, чтобы я мог видеть нижний этаж. Я пытаюсь сделать это, присваивая номера компонентам в моей таблице спрайтов, чтобы, например, в таблице спрайтов размером 1500×500 для фона все это считалось «одним» спрайтом и обрабатывалось как таковое. Ее номер, 1, указан в переменной. Другим примером является таблица спрайтов платформы 240×30, где каждый спрайт размером 60×30 считается «одним» и ему присваивается соответствующий номер, вот так:

 -- Know where the platforms are in the spritesheet
GROUND_LEFT = 1
GROUND_RIGHT = 2
GROUND_SMALL = 3
GROUND_MIDDLE = 4

-- Know where the backgrounds are in the spritesheet
BACKGROUND = 1

[...]
  

Затем я хочу сохранить каждую из них в списке self.tiles, чтобы я мог получить к ним доступ в любое время из таблицы (обратите внимание, что большая часть этого взята из реализации mario CS50, и поэтому я понимаю, если я неправильно понял какие-либо концепции). Однако, когда я запускаю этот код, я получаю следующую ошибку:

 Error

Error

Map.lua:135: bad argument #1 to 'draw' (Texture expected, got nil)


Traceback

[C]: in function 'draw'
Map.lua:135: in function 'render'
main.lua:48: in function 'draw'
[C]: in function 'xpcall'
  

По сути, я просто хочу знать способ, которым я могу установить нижние плитки платформы, а затем иметь возможность выполнять итерации по карте и «устанавливать», где должны быть другие объектные спрайты. Фон сам по себе работает нормально, но как только я добавил:

 -- 'Setting' the platform tiles for where we start
    for x = 1, self.mapWidth do
        self:setTile(x, self.mapHeight - 303, GROUND_MIDDLE)
    end
  

и

 love.graphics.draw(self.platform, self.platformSprite[self:getTile(x, y)],
            (x - 1) * self.platformWidth, (y - 1) * self.platformHeight)
  

строки, программа не запускалась.

Любая помощь приветствуется!

РЕДАКТИРОВАТЬ: строка, в которой я получаю ошибку, является self.platform единственной.

Комментарии:

1. Какая строка Map.lua:135? Это о self.background или self.platform ?

2. Это self.platform one! С этим у меня проблемы.

3. Ок, self.platform есть nil , поэтому вы не можете ее нарисовать. Где вы инициализировали поле platform ? Я не вижу этого в вашем коде.

4. -- 'Setting' the platform tiles for where we start for x = 1, self.mapWidth do self:setTile(x, self.mapHeight - 303, GROUND_MIDDLE) end Не будет ли инициализироваться нужные мне части карты?

5. setTile инициализирует tiles , не platform

Ответ №1:

у меня была такая же проблема раньше, и это оказалось опечаткой при вводе переменной. посмотрев на ваш код, я увидел, что его не было self.platform , вместо этого там было self.platforms .

попробуйте:

 love.graphics.draw(self.platforms, self.platformSprite[self:getTile(x, y)],
        (x - 1) * self.platformWidth, (y - 1) * self.platformHeight)