Necrown - Devlog #10 [Engine Dev] : Game manager et Sauvegarde automatisée des sources du projet
Splix Il y a 12 mois Premium Pro2

Salut les gamecodeurs et gamecodeuses!!!

Aujourd’hui nous allons créer un game manager, qui va gérer les différents états du jeu. Le but est de pouvoir basculer simplement entre le jeu et les différents menus. Commençons donc par aller dans le fichier game.lua pour ajouter un module manager à l’objet game:

local currentState = nil
local states = {}

local debug = nil
if game.inDev then debug = false end
game.manager = {}
game.manager.firstState = nil

function game.manager.init()
  game.manager.setState(game.manager.firstState)
  game.manager.firstState = nil
  game.manager.resize()
end

function game.manager.addState(p_key, p_state)
  assert(states[p_key] == nil, "Duplicate key in states : "..p_key)
  states[p_key] = p_state
end

function game.manager.setState(p_key)
  if p_key ~= nil then currentState = states[p_key]
  else currentState = nil end
end

function game.manager.update()
  if game.inDev and controls.debug.isPressed then
    debug = not debug
  end

  if currentState and currentState.update then
    currentState.update()
  end
end

function game.manager.draw()
  if currentState and currentState.draw then 
    currentState.draw()
  end

  if game.inDev and debug then
    if currentState and currentState.debug then
      currentState.debug()
    end
  end
end

function game.manager.quit()
  if currentState and currentState.quit then
    currentState.quit()
  end
end

Le principe est asses simple: On enregistre les states via la fonction game.manager.addState, et on peut basculer entre chacun d’entre eux via la fonction game.manager.setState. Ensuite game.manager va automatiquement appeler les fonctions du state courant si elles existent. Les fonctions du game manager seront quant à elles appelées directement dans les fonctions de love…

La seule particularité ici est que lorsqu’on est en inDev, on teste si l’on appuie sur le contrôle debug dans game.manager.update, et si c’est le cas on fait basculer l’état de la variable locale debug qui permet de savoir si le mode debug est actif ou non. Nous allons profiter de ce devlog pour faire quelques ajouts à game:

function game.start(p_state)
  game.manager.firstState = p_state
end

game.fps = love.timer.getFPS
game.quit = love.event.quit

On rajoute la fonction game.start, qui permettra de préciser quel state sera lancé au démarrage du jeu, et game.fps et game.quit qui correspondent à love.timer.getFPS et love.event.quit. Voilà pour les modifications sur game. Maintenant nous allons nous attarder un peut sur un autre fichier. Avec tout le travail abattu jusque maintenant, il serait bien de réaliser des sauvegardes régulières, mais vous me connaissez à force, j’ai envie qu’elles soient automatisée. On va donc aller dans notre dossier Excluded et créer un nouveau dossier, qu’on nommera SaveProject, et dedans un nouveau fichier save.cmd dont voici le contenu:

@echo off

:: Calcul du numéro du jour dans l'année (quantième)
:: Ce calcul prend en compte les années bissextiles
if %1.==. (set date=%date%) else (set date=%1)
set day=%date:~0,2%
set i=%day:~0,1%
if %i% EQU 0 set day=%day:~1%
set month=%date:~3,2%
set i=%month:~0,1%
if %i% EQU 0 set month=%month:~1%
set year=%date:~6,4%
set /A mod=year %% 4
set fev=28
if %mod% EQU 0 set /A fev=29
set quant=%day%
if %month% GTR 1 set /A quant=%quant% + 31
if %month% GTR 2 set /A quant=%quant% + fev
if %month% GTR 3 set /A quant=%quant% + 31
if %month% GTR 4 set /A quant=%quant% + 30
if %month% GTR 5 set /A quant=%quant% + 31
if %month% GTR 6 set /A quant=%quant% + 30
if %month% GTR 7 set /A quant=%quant% + 31
if %month% GTR 8 set /A quant=%quant% + 31
if %month% GTR 9 set /A quant=%quant% + 30
if %month% GTR 10 set /A quant=%quant% + 31
if %month% GTR 11 set /A quant=%quant% + 30

:: Ajout de zéros devant le quantième quand il est inférieur à 10 ou à 100
if %quant% LSS 10 set quant=0%quant%
if %quant% LSS 100 set quant=0%quant%

:: Calcul de l'année en ne gardant que les deux derniers chiffres
set year=%date:~8,2%

:: On récupère heures, minutes
:: (Il faut ajouter un zéro à l'heure quand elle est inférieure à 10)
set hour=%time:~0,2%
if %hour% LSS 10 set hour=0%hour%
set minute=%time:~3,2%

:: On copie tout le contenu du jeu dans le dossier de sauvegarde
for /f %%a in ('cd') do set "parent=%%~nxa"
if /i %parent%==SaveProject cd ../../
for /f "tokens=*" %%a in ('cd') do set project=%%a
cd ../
for /f "tokens=*" %%a in ('cd') do set root=%%a
xcopy /I  /Y "%project%" "%root%/Saves/%year%d%quant%_%hour%%minute%"/e

exit

Maintenant, si vous vous souvenez du devlog précédent, on générait un fichier versionHistory.txt, contenant l’historique des versions du jeu, dans un dossier Saves externe au projet. C’est dans ce dossier que notre script va envoyer nos sauvegardes. Les noms de ces dossiers seront de la forme « 2 derniers chiffres de l’année + d + quantième de l’année + _  + heure + minutes ». Comme il s’agit d’un fichier cmd, il suffit de double cliquer dessus pour qu’une sauvegarde complète soit réalisée automatiquement. Mais nous pouvons faire mieux! Nous allons retourner dans notre fichier versioning dans la partie Core du moteur et modifier la fonction versioning.log:

function versioning.log()
  local v = game.version
  local save = os.date('%y').."d"..os.date('%j').."_"..os.date('%H')..os.date('%M')
  
  os.execute("start "..arg[1].."/Excluded/SaveProject/save.cmd")
  
  local log = "{ phase = "..v.phase..", major = "..v.major..", minor = "..v.minor..", patch = "..v.patch
  if v.name ~= nil then log = log..", name = \""..v.name.."\"" end
  log = log..", save = \""..save.."\" }"
  
  local file = io.open("SplixEng/Versioning/versionHistory.lua", "a")
  io.output(file)
  io.write("table.insert(versionHistory, "..log..")\n")
  io.close(file)
  
  local entry = { phase = v.phase, major = v.major, minor = v.minor, patch = v.patch, save = save }
  if v.name ~= nil then entry.name = v.name end
  
  table.insert(versionHistory, entry)
  
  versioning.removeTxt()
end

Vous voyez que maintenant on enregistre également une variable save contenant un code au même format que les noms de fichier de sauvegarde, avant de lancer la sauvegarde via os.execute. La variable arg[1] correspond au chemin du projet, de cette façon on peut changer le projet de place sans que cela ne pose de problème.

Nous avons maintenant une sauvegarde automatique du projet lors d’un changement de version, et il suffit d’afficher le nom du dossier de sauvegarde en même temps que la version dans le fichier texte contenant l’historique, et on pourra les retrouver facilement. J’espère que ce devlog vous aura plu. Nous touchons lentement au but dans l’élaboration de notre moteur, et nous allons bientôt pouvoir commencer à travailler sur le jeu en lui-même. Mais en attendant…

Bon code à tous et à bientôt!!!

Comments (2)

Salut,
Tes devlogs sont très intéressants techniquement, c’est vraiment bien ton travail.
Et concrètement au niveau gameplay tu pourrais nous montrer tes avancements aussi ?

Salut duruti,
Oui c’est prévu, mais voulant faire les choses dans l’ordre où je les fait, j’ai jugé qu’il valait mieux commencer par détailler le développement du moteur.
Je pensais faire encore deux devlogs sur le moteur avant de vraiment voir le développement du jeu, mais suite à ta remarque je réalise que ça commence à faire beaucoup de lignes de code pour trop peu de visuel (pas du tout XD).
J’ai donc décidé de les réunir en un seul devlog et de passer un peu ce qui me paraissait redondant. Là je part en congés trois semaines, à mon retour je présenterai le game concept, et les devlogs suivants seront consacrés au développement du jeu avec, enfin, des visuel 😉

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.