Salut les gamecodeurs et gamecodeuses!!!
Aujourd’hui nous allons continuer notre petit moteur en nous attaquant tout d’abord à la gestion de la fenêtre et de l’affichage… Nous allons donc créer un nouveau fichier dans la partie Core de notre moteur, et nous l’appellerons displaying.lua. L’objet display avait déjà été créé dans le fichier conf lors d’un précédent devlog. Nous allons ici lui rajouter de nouvelles valeurs et des fonctions pour gérer notre fenêtre:
display.s = 1
display.winW = display.w
display.winH = display.h
display.winPos = nil
display.focus = true
function love.focus(p_focus)
display.focus = p_focus
end
local function toFullscreen()
settings.video.fullscreen = true
love.window.setFullscreen(true)
local w = love.graphics.getWidth()
local h = love.graphics.getHeight()
display.s = math.ceil(((w / display.winW) + (h / display.winH)) / 2)
display.w = w / display.s
display.h = h / display.s
end
local function toWindowed()
settings.video.fullscreen = false
love.window.setFullscreen(false)
display.w = display.winW
display.h = display.winH
display.s = 1
end
Vous voyez que l’on créé ici une fonction locale toFullscreen et toWindowed qui gérerons le passage au fullscreen et au fenêtré. Les valeurs display.winW et display.winH enregistrent la largeur et la hauteur de la fenêtre en mode fenêtré, et display.s enregistre l’échelle (un entier qui en mode fenêtré sera égale à 1). Quand on passe en fullscreen, l’échelle est calculée par rapport à la largeur et la hauteur de l’écran. Si les fonctions toFullscreen et toWindowed sont notées locales, c’est parce qu l’on va passer par une autre fonction pour changer le mode de la fenêtre:
function display.init()
if settings.video.fullscreen then toFullscreen() end
display.winPos = love.window.getPosition()
end
function display.toggleFullscreen()
if settings.video.fullscreen then toWindowed()
else toFullscreen() end
settings.video.save()
end
function display.isMoved()
local winPos = love.window.getPosition()
if display.winPos ~= winPos then
display.winPos = winPos
return true
end
return false
end
C’est la fonction display.toggleFullscreen qui s’en chargera, et la fonction display.init sera appelée dans love.init pour tout préparer. La fonction display.isMoved nous sera utile plus tard, elle nous permet de savoir quand la fenêtre est déplacée, et nous nous en servirons pour éviter certains bugs dans ce cas là. Passons maintenant à un nouvel objet: camera. Il s’agit d’une caméra virtuelle qui sera utilisée pour l’affichage du jeu:
camera = {}
camera.x = 0
camera.y = 0
function camera.reset()
camera.x = 0
camera.y = 0
end
function camera.setPos(p_x, p_y)
camera.x = math.floor(p_x - display.w / 2)
camera.y = math.floor(p_y - display.h / 2)
end
function camera.move(p_x, p_y)
camera.setPos(camera.x + p_x, camera.y + p_y)
end
function camera.update() end
La fonction camera.update nous permettra d’appliquer des changements automatiques à la position de la caméra, sinon les déplacements que nous lui indiqueront devront passer par la fonction camera.setPos ou camera.move.
Voici pour résumer à quoi ressemble la fonction update de love dans engine:
function love.update(p_dt)
if not display.isMoved() then
controls.update()
keyboard.update()
mouse.update()
if controls.fullscreen.isPressed then
display.toggleFullscreen()
end
camera.update()
end
mouse.postUpdate()
inputs.postUpdate()
end
Maintenant le jeu peu passer de fullscreen à windowed en appuyant sur f11, et comme la fonction display.toggleFullscreen demande à sauvegarder les video settings à chaque changement, si vous quittez le jeu en fullscreen ou windowed, il se relancera automatiquement dans ce mode. Avant de nous quitter, nous allons d’abord nous amuser à développer notre mode de debug pour l’inDev. Nous allons prendre des instantanés des variables globales au début de engine:
local envLog = nil
if game.inDev then
envLog = {}
envLog["Framework"] = {}
for k, _ in pairs(_G) do
if tostring(k) ~= "game" and tostring(k) ~= "display" and tostring(k) ~= "envLog" then
table.insert(envLog["Framework"], tostring(k))
end
end
end
La variable _G est une variable lua qui contient toutes les variables globales du projet. On enregistre tous leurs noms ici, hormis envLog et les variables créées dans conf, ce qui nous donne toutes les variables globales du lua et de love2d. On va réaliser la même opération à la fin du chargement du moteur, en n’enregistrant que les nouvelles variables, ce qui nous donnera toutes les variables globales ajoutées par le moteur. Puis nous allons rajouter une fonction print à envLog:
function envLog.print(p_state)
local env = {}
if p_state == "Game" then
for k, _ in pairs(_G) do
if not table.contains(envLog["Framework"], tostring(k)) and not table.contains(envLog["Engine"], tostring(k)) then
table.insert(env, tostring(k))
end
end
else
for _, v in pairs(envLog[p_state]) do
table.insert(env, tostring(v))
end
end
string.sort(env)
print(p_state.." environement :")
print("{")
for _, v in ipairs(env) do print("\t"..v) end
print("}".."\n")
end
Avec cette fonction, nous pouvons afficher à tout moment un instantané des variables globales du framework, du moteur et du jeu. On va par la même occasion créer une fonction print à l’objet classes, fonctionnant de la même manière que envLog.print, qui nous permettra d’afficher toutes nos classes. Vous remarquerez peut-être la fonction string.sort, il s’agit encore d’un ajout à l’objet string que nous réalisons dans le fichier stdLib, et qui permet de trier un tableau de string par ordre alphabétique:
local function compare(p_a, p_b)
p_a = tostring(p_a)
p_b = tostring(p_b)
local pattern = '^(.-)%s*(%d+)$'
local _, _, col1, num1 = p_a:find(pattern)
local _, _, col2, num2 = p_b:find(pattern)
if (col1 and col2) and col1 == col2 then
return tonumber(num1) < tonumber(num2)
else
return p_a < p_b
end
end
function string.sort(p_table)
table.sort(p_table, compare)
end
Et voilà, en ajoutant quelques controls, et en vérifiant dans love.update si ils sont pressés, on peut facilement afficher dans la console de love des listes de variables globales ou la liste des classes:
C’est une petite astuce qui peut s’avérer sympa et dont on peut décliner le concept comme on l’entend. Voilà, c’était un devlog asses long. Même si nous avons encore quelques gros points à travailler dans notre moteur, nous allons bientôt pouvoir commencer à vraiment travailler sur le jeu en lui-même. Mais en attendant…
Bon code à tous et à bientôt!!!