local anim8 = require "lib/anim8" require 'lib/vec3' local AssetBundle = require "lib/asset_bundle" local CHARACTER_SIZE = 64 --- Для anim8, представляет из себя с какого по какого представлены спрайты для анимации local ANIMATION_SIZE = '1-6' --- Скорость между кадрами в анимации local ANIMATION_SPEED = 0.1 -- Константы ниже представляют из себя номер строки (с единицы), в которой находится та или иная анимация local IDLE_ROW = 1 local RUN_ROW = 2 local ATTACK_ROW = 3 --- @class Character local character = {} character.__index = character character.name = "" ---------- Animations ----- --- мы должны определиться со спрайтшитами и подобным, всё что здесь написано лишь пример --- --- предполагается, что у всех будет одинаковое кол-во кадров в анимации и их скорость произведения character.animationTable = { idle = {}, run = {}, attack = {} -- etc etc } --- чтобы не обновлять все анимации одновременно, храним нужную анимацию здесь --- меняем вместе с Character.animation character.state = "idle" --- когда нужно сменить анимацию с idle на run например, меняем именно это поле character.spriteSheet = { animationSpeed = 0.1, width = 96, height = 64, idle = '1-6', run = '1-8', attack = '1-11', hurt = '1-6' } ---------- Statistics ----- character.stats = {} --- TODO: придумать формулу расчёта статов относительно уровня character.stats.level = 1 character.stats.initiative = 10 character.stats.damage = 5 character.stats.defence = 0 character.stats.hp = 30 character.player = {} --- TODO: мнимая надежда на спеллмейкинг --- --- правда я абсолютно хз, как он будет смотреться --- в контексте рогалика, но посмотрим --- --- мб это будет метаспеллмейкинг на овощах character.skills = {} character.class = "" character.position = Vec3({}) --- Обёртка над Character:Create -- CreateCharacter = Character.create --- Создаёт персонажа, которым будет управлять или игрок или компьютер --- @param name string --- @param spriteDir table --- @param level? integer local function spawn(name, spriteDir, level) -- aka Character.create(self, name, imagePath, level) -- TODO: добавить asset_loader, где все необходимые ассеты будут грузиться в одном месте, -- а здесь мы добавляем ассет на загрузку в очередь -- local image = love.graphics.newImage(imagePath) local animationGrid = {} -- n: name; i: image for n, i in pairs(spriteDir) do local aGrid = anim8.newGrid(96, 64, i:getWidth(), i:getHeight()) local tiles = '1-' .. math.ceil(i:getWidth() / 96) animationGrid[n] = aGrid(tiles, 1) end --local animationGrid = anim8.newGrid(96, 64, image:getWidth(), image:getHeight()) local char = { name = name, animationTable = { } } char.animationTable.idle = anim8.newAnimation(animationGrid["idle"], ANIMATION_SPEED) char.animationTable.run = anim8.newAnimation(animationGrid["run"], ANIMATION_SPEED) char.animationTable.attack = anim8.newAnimation(animationGrid["attack"], ANIMATION_SPEED, function() char.state = "idle" end) char.animationTable.hurt = anim8.newAnimation(animationGrid["hurt"], ANIMATION_SPEED, function() char.state = "idle" end) char = setmetatable(char, character) table.insert(Tree.level.characters, char) return char end function character:update(dt) if love.keyboard.isDown("r") then self.state = "run" end if love.keyboard.isDown("i") then self.state = "idle" end if love.keyboard.isDown("u") then self.state = "attack" end if love.keyboard.isDown("h") then self.state = "hurt" end self.animationTable[self.state]:update(dt) end function character:draw() local ppm = Tree.level.camera.pixelsPerMeter self.animationTable[self.state]:draw(Tree.assets.files.sprites.character[self.state], self.position.x, self.position.y, nil, 1 / ppm, 1 / ppm, 38, 47) end return { spawn = spawn }