Sphinx-GameClock

Sphinx-GameClock

Comme tous mes plugins, ce script est publié sous licence CC BY 4.0.

Ce que je vous propose aujourd’hui, c’est un système temps réel. Lors du chargement d’une partie (nouvelle partie ou chargement d’une sauvegarde), l’horloge interne du jeu se synchronise avec l’heure renvoyée par le serveur paramétré.

Installer un « serveur de temps »

Ce n’est pas exactement un serveur de temps que nous allons mettre en place. C’est un serveur web classique dont la tache sera de donner l’heure, tout simplement.

Le serveur, ce n’est pas grand chose, c’est seulement une page php hébergée sur internet. Pour que le script suivant fonctionne, vous devez l’héberger sur un serveur faisant tourner PHP en version 5.2.0 minimum (version 7 compatible) :

<?php
    $timezone = null;
    try {
        $timezone = new DateTimeZone($_SERVER["QUERY_STRING"]);
    } catch(Exception $e) {}
    $date = new DateTime("now", $timezone);
    echo $date->format(DATE_RFC3339_EXTENDED);
?>

Après avoir hébergé ce script, vous pouvez le tester en y accédant depuis votre navigateur. Si tout va bien, vous devriez voir affiché la date courante du serveur. Vous pouvez sélectionner un fuseau horaire différent en ajoutant, après le nom du script (probablement index.php) un point d’intérogation (?) suivi du fuseau horaire voulu. Exemple : ?Australia/Sydney pour connaitre l’heure chez les kangourous. Voici la liste des fuseaux horaires supportés par PHP.

Intégrer MomentJS

Maintenant, tout se passe dans votre projet RPG Maker MV. Tout d’abord allez télécharger la dernière version de MomentJS sur le site officiel. Ensuite, prenez l’extension Timezone pour MomentJS. Une fois ces deux scripts téléchargés, intégrez-les comme n’importe quel autre plugin à votre projet RPG Maker MV.

Sphinx-Math.easing

Ajoutez le script Sphinx-MathEasing.js suivant, disponible ici : https://genie23.fr/js-rmmv/sphinx-matheasing/.

Sphinx-GameClock

Maintenant, ajoutez le script Sphinx-GameClock.js avec le contenu suivant dans votre projet :

//=============================================================================
// Sphinx-GameClock.js
//=============================================================================

/*:
 * @plugindesc Système Temps Réel - Gestion du chronomètre et de la teinte de l'écran
 * @author Sphinx
 *
 * @help
 * Gestion du jour et de l'heure fictive avec synchronisation côté serveur. A
 * noter que comme ce script gère la teinte de l'écran, il ne sera plus possible
 * d'utiliser la commande d'event Modifier la teinte de l'écran.
 * 
 * Commandes de messages :
 *     \DATE[FORMAT] : Met en forme la date courante dans le format FORMAT.
 *                     Le format doit être un format MomentJs valide.
 * 
 * Commandes de plugin :
 *     - FIXER_DATE DATE :
 *         Modifie arbitrairement la date et l'heure du jeu. La date doit être
 *         passée au format suivant : DD/MM/YYYY HH:mm.
 *     - FIXER_TIMEZONE TIMEZONE
 *         Modifie arbitrairement le fuseau horaire vers TIMEZONE.
 * 
 * Dépendances : - MomentJS et son extension Timezone (https://momentjs.com/)
 *               - Math.easing
 * 
 * @param configLabels
 * @text Configuration des noms de jours et mois
 * @desc Configuration des noms de jours et mois de l'année.
 * 
 * @param listShortDays
 * @parent configLabels
 * @text Liste des jours de la semaine
 * @type text[]
 * @default [ "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam", "Dim" ]
 * 
 * @param listLongDays
 * @parent configLabels
 * @text Liste des jours de la semaine
 * @type text[]
 * @default [ "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche" ]
 * 
 * @param listShortMonth
 * @parent configLabels
 * @text Liste des mois
 * @type text[]
 * @default [ "Jan", "Fév", "Mars", "Avr", "Mai", "Juin", "Juil", "Août", "Sept", "Oct", "Nov", "Déc" ]
 * 
 * @param listLongMonth
 * @parent configLabels
 * @text Liste des mois
 * @type text[]
 * @default [ "Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre" ]
 * 
 * @param configSystem
 * @text Configuration du système temps réel
 * @desc Configuration des paramètres du système de temps réel (adresse serveur, fuseau horaire, teintes de l'écran).
 * 
 * @param easingMethod
 * @parent configSystem
 * @text Méthode d'accélération
 * @desc Méthode d'accélération qui sera appliquée à la modification de la teinte de l'écran.
 * @type combo
 * @option linearTween
 * @option easeInQuad
 * @option easeOutQuad
 * @option easeInOutQuad
 * @option easeInCubic
 * @option easeOutCubic
 * @option easeInOutCubic
 * @option easeInQuart
 * @option easeOutQuart
 * @option easeInOutQuart
 * @option easeInQuint
 * @option easeOutQuint
 * @option easeInOutQuint
 * @option easeInSine
 * @option easeOutSine
 * @option easeInOutSine
 * @option easeInExpo
 * @option easeOutExpo
 * @option easeInOutExpo
 * @option easeInCirc
 * @option easeOutCirc
 * @option easeInOutCirc
 * @default easeInCirc
 * 
 * @param tints
 * @text Teintes d'écran
 * @desc Teintes d'écran, selon l'heure de la journée.
 * @parent configSystem
 * @type struct<tint>[]
 * @default ["{\"color\":\"{\\\"red\\\":\\\"-68\\\",\\\"green\\\":\\\"-68\\\",\\\"blue\\\":\\\"0\\\",\\\"gray\\\":\\\"68\\\"}\",\"time\":\"{\\\"hour\\\":\\\"4\\\",\\\"minutes\\\":\\\"0\\\"}\"}","{\"color\":\"{\\\"red\\\":\\\"68\\\",\\\"green\\\":\\\"-34\\\",\\\"blue\\\":\\\"-34\\\",\\\"gray\\\":\\\"0\\\"}\",\"time\":\"{\\\"hour\\\":\\\"6\\\",\\\"minutes\\\":\\\"0\\\"}\"}","{\"color\":\"{\\\"red\\\":\\\"0\\\",\\\"green\\\":\\\"0\\\",\\\"blue\\\":\\\"0\\\",\\\"gray\\\":\\\"0\\\"}\",\"time\":\"{\\\"hour\\\":\\\"9\\\",\\\"minutes\\\":\\\"0\\\"}\"}","{\"color\":\"{\\\"red\\\":\\\"0\\\",\\\"green\\\":\\\"0\\\",\\\"blue\\\":\\\"0\\\",\\\"gray\\\":\\\"0\\\"}\",\"time\":\"{\\\"hour\\\":\\\"17\\\",\\\"minutes\\\":\\\"0\\\"}\"}","{\"color\":\"{\\\"red\\\":\\\"68\\\",\\\"green\\\":\\\"-34\\\",\\\"blue\\\":\\\"-34\\\",\\\"gray\\\":\\\"0\\\"}\",\"time\":\"{\\\"hour\\\":\\\"20\\\",\\\"minutes\\\":\\\"0\\\"}\"}","{\"color\":\"{\\\"red\\\":\\\"-68\\\",\\\"green\\\":\\\"-68\\\",\\\"blue\\\":\\\"0\\\",\\\"gray\\\":\\\"68\\\"}\",\"time\":\"{\\\"hour\\\":\\\"22\\\",\\\"minutes\\\":\\\"0\\\"}\"}"]
 * 
 * @param urlNtp
 * @parent configSystem
 * @text Adresse URL NTP
 * @desc URL vers la page ntp.php. %1 sera remplacé par le fuseau horaire demandé.
 * @default https://ntp.genie23.fr/?%1
 * 
 * @param timezone
 * @parent configSystem
 * @text Fuseau horaire appliqué
 * @desc Fuseau horaire appliqué au jeu.
 * @default Europe/Paris 
 * @type combo
 * @option Africa/Abidjan
 * @option Africa/Accra
 * @option Africa/Addis_Ababa
 * @option Africa/Algiers
 * @option Africa/Asmara
 * @option Africa/Bamako
 * @option Africa/Bangui
 * @option Africa/Banjul
 * @option Africa/Bissau
 * @option Africa/Blantyre
 * @option Africa/Brazzaville
 * @option Africa/Bujumbura
 * @option Africa/Cairo
 * @option Africa/Casablanca
 * @option Africa/Ceuta
 * @option Africa/Conakry
 * @option Africa/Dakar
 * @option Africa/Dar_es_Salaam
 * @option Africa/Djibouti
 * @option Africa/Douala
 * @option Africa/El_Aaiun
 * @option Africa/Freetown
 * @option Africa/Gaborone
 * @option Africa/Harare
 * @option Africa/Johannesburg
 * @option Africa/Juba
 * @option Africa/Kampala
 * @option Africa/Khartoum
 * @option Africa/Kigali
 * @option Africa/Kinshasa
 * @option Africa/Lagos
 * @option Africa/Libreville
 * @option Africa/Lome
 * @option Africa/Luanda
 * @option Africa/Lubumbashi
 * @option Africa/Lusaka
 * @option Africa/Malabo
 * @option Africa/Maputo
 * @option Africa/Maseru
 * @option Africa/Mbabane
 * @option Africa/Mogadishu
 * @option Africa/Monrovia
 * @option Africa/Nairobi
 * @option Africa/Ndjamena
 * @option Africa/Niamey
 * @option Africa/Nouakchott
 * @option Africa/Ouagadougou
 * @option Africa/Porto-Novo
 * @option Africa/Sao_Tome
 * @option Africa/Tripoli
 * @option Africa/Tunis
 * @option Africa/Windhoek
 * @option America/Adak
 * @option America/Anchorage
 * @option America/Anguilla
 * @option America/Antigua
 * @option America/Araguaina
 * @option America/Argentina/Buenos_Aires
 * @option America/Argentina/Catamarca
 * @option America/Argentina/Cordoba
 * @option America/Argentina/Jujuy
 * @option America/Argentina/La_Rioja
 * @option America/Argentina/Mendoza
 * @option America/Argentina/Rio_Gallegos
 * @option America/Argentina/Salta
 * @option America/Argentina/San_Juan
 * @option America/Argentina/San_Luis
 * @option America/Argentina/Tucuman
 * @option America/Argentina/Ushuaia
 * @option America/Aruba
 * @option America/Asuncion
 * @option America/Atikokan
 * @option America/Bahia
 * @option America/Bahia_Banderas
 * @option America/Barbados
 * @option America/Belem
 * @option America/Belize
 * @option America/Blanc-Sablon
 * @option America/Boa_Vista
 * @option America/Bogota
 * @option America/Boise
 * @option America/Cambridge_Bay
 * @option America/Campo_Grande
 * @option America/Cancun
 * @option America/Caracas
 * @option America/Cayenne
 * @option America/Cayman
 * @option America/Chicago
 * @option America/Chihuahua
 * @option America/Costa_Rica
 * @option America/Creston
 * @option America/Cuiaba
 * @option America/Curacao
 * @option America/Danmarkshavn
 * @option America/Dawson
 * @option America/Dawson_Creek
 * @option America/Denver
 * @option America/Detroit
 * @option America/Dominica
 * @option America/Edmonton
 * @option America/Eirunepe
 * @option America/El_Salvador
 * @option America/Fort_Nelson
 * @option America/Fortaleza
 * @option America/Glace_Bay
 * @option America/Godthab
 * @option America/Goose_Bay
 * @option America/Grand_Turk
 * @option America/Grenada
 * @option America/Guadeloupe
 * @option America/Guatemala
 * @option America/Guayaquil
 * @option America/Guyana
 * @option America/Halifax
 * @option America/Havana
 * @option America/Hermosillo
 * @option America/Indiana/Indianapolis
 * @option America/Indiana/Knox
 * @option America/Indiana/Marengo
 * @option America/Indiana/Petersburg
 * @option America/Indiana/Tell_City
 * @option America/Indiana/Vevay
 * @option America/Indiana/Vincennes
 * @option America/Indiana/Winamac
 * @option America/Inuvik
 * @option America/Iqaluit
 * @option America/Jamaica
 * @option America/Juneau
 * @option America/Kentucky/Louisville
 * @option America/Kentucky/Monticello
 * @option America/Kralendijk
 * @option America/La_Paz
 * @option America/Lima
 * @option America/Los_Angeles
 * @option America/Lower_Princes
 * @option America/Maceio
 * @option America/Managua
 * @option America/Manaus
 * @option America/Marigot
 * @option America/Martinique
 * @option America/Matamoros
 * @option America/Mazatlan
 * @option America/Menominee
 * @option America/Merida
 * @option America/Metlakatla
 * @option America/Mexico_City
 * @option America/Miquelon
 * @option America/Moncton
 * @option America/Monterrey
 * @option America/Montevideo
 * @option America/Montserrat
 * @option America/Nassau
 * @option America/New_York
 * @option America/Nipigon
 * @option America/Nome
 * @option America/Noronha
 * @option America/North_Dakota/Beulah
 * @option America/North_Dakota/Center
 * @option America/North_Dakota/New_Salem
 * @option America/Ojinaga
 * @option America/Panama
 * @option America/Pangnirtung
 * @option America/Paramaribo
 * @option America/Phoenix
 * @option America/Port-au-Prince
 * @option America/Port_of_Spain
 * @option America/Porto_Velho
 * @option America/Puerto_Rico
 * @option America/Punta_Arenas
 * @option America/Rainy_River
 * @option America/Rankin_Inlet
 * @option America/Recife
 * @option America/Regina
 * @option America/Resolute
 * @option America/Rio_Branco
 * @option America/Santarem
 * @option America/Santiago
 * @option America/Santo_Domingo
 * @option America/Sao_Paulo
 * @option America/Scoresbysund
 * @option America/Sitka
 * @option America/St_Barthelemy
 * @option America/St_Johns
 * @option America/St_Kitts
 * @option America/St_Lucia
 * @option America/St_Thomas
 * @option America/St_Vincent
 * @option America/Swift_Current
 * @option America/Tegucigalpa
 * @option America/Thule
 * @option America/Thunder_Bay
 * @option America/Tijuana
 * @option America/Toronto
 * @option America/Tortola
 * @option America/Vancouver
 * @option America/Whitehorse
 * @option America/Winnipeg
 * @option America/Yakutat
 * @option America/Yellowknife
 * @option Antarctica/Casey
 * @option Antarctica/Davis
 * @option Antarctica/DumontDUrville
 * @option Antarctica/Macquarie
 * @option Antarctica/Mawson
 * @option Antarctica/McMurdo
 * @option Antarctica/Palmer
 * @option Antarctica/Rothera
 * @option Antarctica/Syowa
 * @option Antarctica/Troll
 * @option Antarctica/Vostok
 * @option Arctic/Longyearbyen
 * @option Asia/Aden
 * @option Asia/Almaty
 * @option Asia/Amman
 * @option Asia/Anadyr
 * @option Asia/Aqtau
 * @option Asia/Aqtobe
 * @option Asia/Ashgabat
 * @option Asia/Atyrau
 * @option Asia/Baghdad
 * @option Asia/Bahrain
 * @option Asia/Baku
 * @option Asia/Bangkok
 * @option Asia/Barnaul
 * @option Asia/Beirut
 * @option Asia/Bishkek
 * @option Asia/Brunei
 * @option Asia/Chita
 * @option Asia/Choibalsan
 * @option Asia/Colombo
 * @option Asia/Damascus
 * @option Asia/Dhaka
 * @option Asia/Dili
 * @option Asia/Dubai
 * @option Asia/Dushanbe
 * @option Asia/Famagusta
 * @option Asia/Gaza
 * @option Asia/Hebron
 * @option Asia/Ho_Chi_Minh
 * @option Asia/Hong_Kong
 * @option Asia/Hovd
 * @option Asia/Irkutsk
 * @option Asia/Jakarta
 * @option Asia/Jayapura
 * @option Asia/Jerusalem
 * @option Asia/Kabul
 * @option Asia/Kamchatka
 * @option Asia/Karachi
 * @option Asia/Kathmandu
 * @option Asia/Khandyga
 * @option Asia/Kolkata
 * @option Asia/Krasnoyarsk
 * @option Asia/Kuala_Lumpur
 * @option Asia/Kuching
 * @option Asia/Kuwait
 * @option Asia/Macau
 * @option Asia/Magadan
 * @option Asia/Makassar
 * @option Asia/Manila
 * @option Asia/Muscat
 * @option Asia/Nicosia
 * @option Asia/Novokuznetsk
 * @option Asia/Novosibirsk
 * @option Asia/Omsk
 * @option Asia/Oral
 * @option Asia/Phnom_Penh
 * @option Asia/Pontianak
 * @option Asia/Pyongyang
 * @option Asia/Qatar
 * @option Asia/Qostanay
 * @option Asia/Qyzylorda
 * @option Asia/Riyadh
 * @option Asia/Sakhalin
 * @option Asia/Samarkand
 * @option Asia/Seoul
 * @option Asia/Shanghai
 * @option Asia/Singapore
 * @option Asia/Srednekolymsk
 * @option Asia/Taipei
 * @option Asia/Tashkent
 * @option Asia/Tbilisi
 * @option Asia/Tehran
 * @option Asia/Thimphu
 * @option Asia/Tokyo
 * @option Asia/Tomsk
 * @option Asia/Ulaanbaatar
 * @option Asia/Urumqi
 * @option Asia/Ust-Nera
 * @option Asia/Vientiane
 * @option Asia/Vladivostok
 * @option Asia/Yakutsk
 * @option Asia/Yangon
 * @option Asia/Yekaterinburg
 * @option Asia/Yerevan
 * @option Atlantic/Azores
 * @option Atlantic/Bermuda
 * @option Atlantic/Canary
 * @option Atlantic/Cape_Verde
 * @option Atlantic/Faroe
 * @option Atlantic/Madeira
 * @option Atlantic/Reykjavik
 * @option Atlantic/South_Georgia
 * @option Atlantic/St_Helena
 * @option Atlantic/Stanley
 * @option Australia/Adelaide
 * @option Australia/Brisbane
 * @option Australia/Broken_Hill
 * @option Australia/Currie
 * @option Australia/Darwin
 * @option Australia/Eucla
 * @option Australia/Hobart
 * @option Australia/Lindeman
 * @option Australia/Lord_Howe
 * @option Australia/Melbourne
 * @option Australia/Perth
 * @option Australia/Sydney
 * @option Europe/Amsterdam
 * @option Europe/Andorra
 * @option Europe/Astrakhan
 * @option Europe/Athens
 * @option Europe/Belgrade
 * @option Europe/Berlin
 * @option Europe/Bratislava
 * @option Europe/Brussels
 * @option Europe/Bucharest
 * @option Europe/Budapest
 * @option Europe/Busingen
 * @option Europe/Chisinau
 * @option Europe/Copenhagen
 * @option Europe/Dublin
 * @option Europe/Gibraltar
 * @option Europe/Guernsey
 * @option Europe/Helsinki
 * @option Europe/Isle_of_Man
 * @option Europe/Istanbul
 * @option Europe/Jersey
 * @option Europe/Kaliningrad
 * @option Europe/Kiev
 * @option Europe/Kirov
 * @option Europe/Lisbon
 * @option Europe/Ljubljana
 * @option Europe/London
 * @option Europe/Luxembourg
 * @option Europe/Madrid
 * @option Europe/Malta
 * @option Europe/Mariehamn
 * @option Europe/Minsk
 * @option Europe/Monaco
 * @option Europe/Moscow
 * @option Europe/Oslo
 * @option Europe/Paris
 * @option Europe/Podgorica
 * @option Europe/Prague
 * @option Europe/Riga
 * @option Europe/Rome
 * @option Europe/Samara
 * @option Europe/San_Marino
 * @option Europe/Sarajevo
 * @option Europe/Saratov
 * @option Europe/Simferopol
 * @option Europe/Skopje
 * @option Europe/Sofia
 * @option Europe/Stockholm
 * @option Europe/Tallinn
 * @option Europe/Tirane
 * @option Europe/Ulyanovsk
 * @option Europe/Uzhgorod
 * @option Europe/Vaduz
 * @option Europe/Vatican
 * @option Europe/Vienna
 * @option Europe/Vilnius
 * @option Europe/Volgograd
 * @option Europe/Warsaw
 * @option Europe/Zagreb
 * @option Europe/Zaporozhye
 * @option Europe/Zurich
 * @option Indian/Antananarivo
 * @option Indian/Chagos
 * @option Indian/Christmas
 * @option Indian/Cocos
 * @option Indian/Comoro
 * @option Indian/Kerguelen
 * @option Indian/Mahe
 * @option Indian/Maldives
 * @option Indian/Mauritius
 * @option Indian/Mayotte
 * @option Indian/Reunion
 * @option Pacific/Apia
 * @option Pacific/Auckland
 * @option Pacific/Bougainville
 * @option Pacific/Chatham
 * @option Pacific/Chuuk
 * @option Pacific/Easter
 * @option Pacific/Efate
 * @option Pacific/Enderbury
 * @option Pacific/Fakaofo
 * @option Pacific/Fiji
 * @option Pacific/Funafuti
 * @option Pacific/Galapagos
 * @option Pacific/Gambier
 * @option Pacific/Guadalcanal
 * @option Pacific/Guam
 * @option Pacific/Honolulu
 * @option Pacific/Kiritimati
 * @option Pacific/Kosrae
 * @option Pacific/Kwajalein
 * @option Pacific/Majuro
 * @option Pacific/Marquesas
 * @option Pacific/Midway
 * @option Pacific/Nauru
 * @option Pacific/Niue
 * @option Pacific/Norfolk
 * @option Pacific/Noumea
 * @option Pacific/Pago_Pago
 * @option Pacific/Palau
 * @option Pacific/Pitcairn
 * @option Pacific/Pohnpei
 * @option Pacific/Port_Moresby
 * @option Pacific/Rarotonga
 * @option Pacific/Saipan
 * @option Pacific/Tahiti
 * @option Pacific/Tarawa
 * @option Pacific/Tongatapu
 * @option Pacific/Wake
 * @option Pacific/Wallis
 * 
 * @param configEvent
 * @text Configuration événementielle
 * @desc Configuration des interrupteurs et variables associées à la gestion du temps.
 * 
 * @param switches
 * @parent configEvent
 * @text Switches
 * 
 * @param interiorSwitch
 * @parent switches
 * @text Switch intérieur/extérieur
 * @desc Switch définissant si le héros est dans un bâtiment (switch on) ou à l'extérieur (switch off). La teinte de l'écran n'est appliquée qu'en extérieur.
 * @type switch
 * @default 1
 * 
 * @param variables
 * @parent configEvent
 * @text Variables
 * 
 * @param yearVariable
 * @parent variables
 * @text Variable année
 * @desc Variable dans laquelle est stockée l'année actuelle.
 * @type variable
 * @default 1
 * 
 * @param monthVariable
 * @parent variables
 * @text Variable mois
 * @desc Variable dans laquelle est stockée le mois actuel (janvier = 1, décembre = 0).
 * @type variable
 * @default 2
 * 
 * @param dayWeekVariable
 * @parent variables
 * @text Variable jour de la semaine
 * @desc Variable dans laquelle est stockée le jour de la semaine actuel (lundi = 1, dimanche = 7).
 * @type variable
 * @default 3
 * 
 * @param dayVariable
 * @parent variables
 * @text Variable jour du mois
 * @desc Variable dans laquelle est stockée le jour du mois actuel.
 * @type variable
 * @default 4
 * 
 * @param hourVariable
 * @parent variables
 * @text Variable heure
 * @desc Variable dans laquelle est stockée l'heure actuelle.
 * @type variable
 * @default 5
 * 
 * @param minutesVariable
 * @parent variables
 * @text Variable minutes
 * @desc Variable dans laquelle est stockée les minutes actuelles.
 * @type variable
 * @default 6
 * 
 * @param secondesVariable
 * @parent variables
 * @text Variable secondes
 * @desc Variable dans laquelle est stockée les secondes actuelles.
 * @type variable
 * @default 7
 */
/*~struct~tint:
 * @param color
 * @desc Couleur de teinte de l'écran. La teinte normale est de 0, 0, 0, 0.
 * @type struct<tintColor>
 * @default {"red":"0","green":"0","blue":"0","gray":"0"}
 * 
 * @param time
 * @desc Heure à laquelle cette teinte sera appliquée.
 * @type struct<time>
 * @default {"hour":"0","minutes":"0"}
 */
/*~struct~tintColor:
 * @param red
 * @desc Niveau de rouge de la teinte de l'écran.
 * @type number
 * @default 0
 * @min -255
 * @max 255
 * 
 * @param green
 * @desc Niveau de vert de la teinte de l'écran.
 * @type number
 * @default 0
 * @min -255
 * @max 255
 * 
 * @param blue
 * @desc Niveau de bleu de la teinte de l'écran.
 * @type number
 * @default 0
 * @min -255
 * @max 255
 * 
 * @param gray
 * @desc Niveau de bleu de la teinte de l'écran. Plus cette valeur est élevée et plus la teinte virera vers le noir et blanc.
 * @type number
 * @default 0
 * @min 0
 * @max 255
 */
/*~struct~time:
 * @param hour
 * @desc Heure (24 heures)
 * @type number
 * @default 0
 * @min 0
 * @max 23
 * 
 * @param minutes
 * @desc Minutes
 * @type number
 * @default 0
 * @min 0
 * @max 59
 */
// Récupération des paramètres du plugin
moment.updateLocale("fr", {
    months : 'Janvier_Février_Mars_Avril_Mai_Juin_Juillet_Août_Septembre_Octobre_Novembre_Décembre'.split('_'),
    monthsShort : 'Janv._Févr._Mars_Avr._Mai_Juin_Juil._Août_Sept._Oct._Nov._Déc.'.split('_'),
    weekdays : 'Dimanche_Lundi_Mardi_Mercredi_Jeudi_Vendredi_Samedi'.split('_'),
    weekdaysShort : 'Dim._Lun._Mar._Mer._Jeu._Ven._Sam.'.split('_'),
    weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'),
    week : {
        dow : 1, // Monday is the first day of the week.
        doy : 4  // Used to determine first week of the year.
    }
});
const DAYS_LABELS = moment()._locale._weekdaysShort;
const EASING_METHOD = PluginManager.parameters('Sphinx-GameClock')["easingMethod"];
const NTP_URL = PluginManager.parameters('Sphinx-GameClock')["urlNtp"];
DEFAULT_TIMEZONE = PluginManager.parameters('Sphinx-GameClock')["timezone"];
SCREEN_TINTS = JSON.parse(PluginManager.parameters('Sphinx-GameClock')["tints"]);
SWITCHES = {
    interiorSwitch: PluginManager.parameters('Sphinx-GameClock')["interiorSwitch"]
};
VARIABLES = {
    yearVariable: PluginManager.parameters('Sphinx-GameClock')["yearVariable"],
    monthVariable: PluginManager.parameters('Sphinx-GameClock')["monthVariable"],
    dayWeekVariable: PluginManager.parameters('Sphinx-GameClock')["dayWeekVariable"],
    dayVariable: PluginManager.parameters('Sphinx-GameClock')["dayVariable"],
    hourVariable: PluginManager.parameters('Sphinx-GameClock')["hourVariable"],
    minutesVariable: PluginManager.parameters('Sphinx-GameClock')["minutesVariable"],
    secondesVariable: PluginManager.parameters('Sphinx-GameClock')["secondesVariable"]
};

// Réhydratation des teintes d'écran
for(i = 0; i < SCREEN_TINTS.length; ++i) {
    SCREEN_TINTS[i] = JSON.parse(SCREEN_TINTS[i]);
    SCREEN_TINTS[i].color = JSON.parse(SCREEN_TINTS[i].color);
    for(key of Object.keys(SCREEN_TINTS[i].color)) {
        SCREEN_TINTS[i].color[key] = parseInt(SCREEN_TINTS[i].color[key], 10);
    }
    SCREEN_TINTS[i].time = JSON.parse(SCREEN_TINTS[i].time);
    for(key of Object.keys(SCREEN_TINTS[i].time)) {
        SCREEN_TINTS[i].time[key] = parseInt(SCREEN_TINTS[i].time[key], 10);
    }
};

// Tri des teintes en fonction de leurs heures respectives
SCREEN_TINTS.sort(function(a, b) {
    if(a.time.hour < b.time.hour || (a.time.hour == b.time.hour && a.time.minutes < b.time.minutes)) {
        return -1;
    } else if(a.time.hour == b.time.hour && a.time.minutes == b.time.minutes) {
        return 0;
    }
    return 1;
});

//-----------------------------------------------------------------------------
// DataManager
DataManager.SphinxGameClockCreateGameObjects = DataManager.createGameObjects;
DataManager.createGameObjects = function() {
    DataManager.SphinxGameClockCreateGameObjects.call(this);
    $gameClock = new Game_Clock();
};

DataManager.SphinxGameClockMakeSaveContents = DataManager.makeSaveContents;
DataManager.makeSaveContents = function() {
    var contents = DataManager.SphinxGameClockMakeSaveContents.call(this);
    contents.clock = $gameClock;
    return contents;
};

DataManager.SphinxGameClockExtractSaveContents = DataManager.extractSaveContents;
DataManager.extractSaveContents = function(contents) {
    DataManager.SphinxGameClockExtractSaveContents.call(this, contents);
    $gameClock = contents.clock;
};

DataManager.SphinxGameClockLoadGame = DataManager.loadGame;
DataManager.loadGame = function(savefileId) {
    try {
        if(DataManager.SphinxGameClockLoadGame.call(this, savefileId)) {
            $gameClock.synchronize();
            return true;
        } else {
            return false;
        }
    } catch (e) {
        console.error(e);
        return false;
    }
};

//-----------------------------------------------------------------------------
// Game_Interpreter
Game_Interpreter.prototype.SphinxGameClockPluginCommand = Game_Interpreter.prototype.pluginCommand;
Game_Interpreter.prototype.pluginCommand = function(command, args) {
    switch(command) {
        // Modifie la date du jeu
        case "FIXER_DATE":
            newDate = moment(args.join(" "), "DD/MM/YYYY HH:mm").tz($gameClock.getTimezone());
            $gameClock.addGap(newDate - $gameClock.getTime());
            break;
        // Modifie le fuseau horaire du jeu
        case "FIXER_TIMEZONE":
            $gameClock.setTimezone(args[0]);
            break;
        default:
            Game_Interpreter.prototype.SphinxGameClockPluginCommand.call(this, command, args);
            break;
    }
};

//-----------------------------------------------------------------------------
// Game_Clock
var $gameClock;
function Game_Clock() {
    this.initialize.apply(this, arguments);
};

Game_Clock.prototype.initialize = function() {
    this._timeServer = moment();
    this.setTimezone(DEFAULT_TIMEZONE);
    this._gap = 0;
    
    // Synchronisation du temps depuis le serveur
    this.synchronize();
    
    // Nettoyage de l'intervalle si nécessaire
    if($gameClock && $gameClock._interval) {
        clearInterval($gameClock._interval);
    }

    // Initialisation de l'intervalle
    this._interval = setInterval((() => {
        this._timeServer.add(500, "milliseconds");
        this.update();
    }).bind(this), 500);
};

Game_Clock.prototype.synchronize = function() {
    const requete = new XMLHttpRequest();
    requete.onreadystatechange = (function(event) {
        if(requete.readyState === XMLHttpRequest.DONE) {
            if(requete.status === 200) {
                this._timeServer = moment(requete.responseText).tz(this._timezone).locale("fr");
                var delai = 1000 - (this._timeServer % 1000);
                setTimeout((() => {
                    this._timeServer.add(delai, "milliseconds");
                }).bind(this), delai);
            } else {
                throw new Error(requete.statusText);
            }
        }
    }).bind(this);

    requete.open('GET', NTP_URL.replace("%1", this._timezone), true);
    requete.send();
};

Game_Clock.prototype.update = function() {
    date = this.getTime();
    $gameVariables.setValue(VARIABLES.yearVariable, parseInt(date.format("Y"), 10));
    $gameVariables.setValue(VARIABLES.monthVariable, parseInt(date.format("M"), 10));
    $gameVariables.setValue(VARIABLES.dayWeekVariable, parseInt(date.format("E"), 10));
    $gameVariables.setValue(VARIABLES.dayVariable, parseInt(date.format("D"), 10));
    $gameVariables.setValue(VARIABLES.hourVariable, parseInt(date.format("H"), 10));
    $gameVariables.setValue(VARIABLES.minutesVariable, parseInt(date.format("m"), 10));
    $gameVariables.setValue(VARIABLES.secondesVariable, parseInt(date.format("s"), 10));
    this.updateScreenTint();
};

Game_Clock.prototype.updateScreenTint = function() {
    time = $gameClock.getTime();
    fromTint = this.getPreviousTint();
    toTint = this.getNextTint();
    
    tintMod = { color: {}, time: {} };
    for(c of Object.keys(fromTint.color)) {
        tintMod.color[c] = toTint.color[c] - fromTint.color[c];
    }
    tintMod.time.hour = (toTint.time.hour < fromTint.time.hour ? 24 : 0) + toTint.time.hour - fromTint.time.hour;
    tintMod.time.minutes = (toTint.time.minutes < fromTint.time.minutes ? 60 : 0) + toTint.time.minutes - fromTint.time.minutes;
    
    tintMod.time.elapsed = ((time.hours() < fromTint.time.hour ? 24 : 0) + time.hours() - fromTint.time.hour) * 3600 + ((time.minutes() < fromTint.time.minutes ? 24 : 0) + time.minutes() - fromTint.time.minutes) * 60;
    tintMod.time.duration = tintMod.time.hour * 3600 + tintMod.time.minutes * 60;
    
    newTint = [];
    for(c of Object.keys(tintMod.color)) {
        newTint.push(Math.easing[EASING_METHOD](tintMod.time.elapsed, fromTint.color[c], tintMod.color[c], tintMod.time.duration));
    }
    if($gameSwitches.value(SWITCHES.interiorSwitch)) $gameScreen._tone = [ 0, 0, 0, 0 ];
    else $gameScreen._tone = newTint;
};

Game_Clock.prototype.getPreviousTint = function() {
    time = this.getTime();
    for(i = SCREEN_TINTS.length - 1; i >= 0; --i) {
        tint = SCREEN_TINTS[i];
        if(tint.time.hour < time.hour() || (tint.time.hour == time.hour() && tint.time.minutes < time.minutes())) {
            return SCREEN_TINTS[i];
        }
    }
    return SCREEN_TINTS[SCREEN_TINTS.length - 1];
};

Game_Clock.prototype.getNextTint = function() {
    time = this.getTime();
    for(i = 0; i < SCREEN_TINTS.length - 1; ++i) {
        tint = SCREEN_TINTS[i];
        if(tint.time.hour > time.hour() || (tint.time.hour == time.hour() && tint.time.minutes > time.minutes())) {
            return tint;
        }
    }
    return SCREEN_TINTS[0];
};

Game_Clock.prototype.addGap = function(milliseconds) {
    this._gap += milliseconds;
};

Game_Clock.prototype.subtractGap = function(milliseconds) {
    this._gap -= milliseconds;
};

Game_Clock.prototype.getTimezone = function() {
    return this._timezone;
};

Game_Clock.prototype.setTimezone = function(timezone) {
    this._timezone = timezone;
    this._timeServer.tz(this._timezone);
};

Game_Clock.prototype.getTime = function() {
    return this._timeServer.clone().add(this._gap, "milliseconds");
};

//-----------------------------------------------------------------------------
// Window_Base
Window_Base.prototype.SphinxGameClock_convertEscapeCharacters = Window_Base.prototype.convertEscapeCharacters;
Window_Base.prototype.convertEscapeCharacters = function(text) {
    text = Window_Base.prototype.SphinxGameClock_convertEscapeCharacters.call(this, text);

    // \DATE[Format]
    text = text.replace(/\x1bDATE\[(.+)\]/gi, function() {
        return $gameClock.getTime().format(arguments[1]);
    }.bind(this));
    
    return text;
};

Ce script gère la synchronisation avec le serveur, la mise à jour de l’horloge (toutes les demies secondes environ), la localisation dans un fuseau horaire, mais également la teinte de l’écran. A noter qu’à cause de ce dernier point, la commande d’évènement Modifier la teinte de l’écran… n’aura plus d’effet.

Ce plugin définit également deux commandes de plugin pour modifier l’heure interne du jeu. En effet, si le système sait se synchroniser avec l’heure réelle pour gérer l’écoulement du temps, il est aussi capable de maintenir un écart constant entre l’heure réelle du serveur et l’heure du jeu.

Voici les commandes de plugin disponibles :

  • FIXER_DATE DATE
    Modifie la date et l’heure du jeu. DATE doit être une date au format DD/MM/YYYY HH:mm.
  • FIXER_TIMEZONE TIMEZONE
    Modifie le fuseau horaire du jeu. TIMEZONE doit être un des fuseaux supporté par le système. Voir la liste des fuseaux horaires supportés par PHP (et donc par mon système).

A noter que la commande FIXER_DATE fixe l’heure dans le fuseau horaire actuel. Si vous voulez changer l’heure dans un nouveau fuseau horaire, il faut d’abord fixer le fuseau horaire puis fixer l’heure.

Et bien sûr, vous pouvez également afficher la date au format que vous voulez grace à la nouvelle commande de messages \DATE[FORMAT] où FORMAT est un format pris en charge par MomentJS.

Scènes de modification du temps interne du jeu

Ce qui suit n’est pas indispensable pour que le système fonctionne. Il s’agit de deux scènes qui permettront au joueur de choisir lui même le jour et l’heure interne du jeu. Elles sont loin d’être parfaites – elles fonctionnent techniquement, mais elles ne sont pas travaillées graphiquement -, mais ces bricolages pourront vous servir de base.

Sphinx-SceneCalendar

Je vais commencer par Sphinx-SceneCalendar, la scène de modification du jour. Avec la commande de plugin REGLER_CALENDRIER, la scène s’ouvrira et affichera un calendrier qui gère les week-ends et les jours fériés. En cliquant sur les boutons autour du nom du mois en haut, le joueur pourra naviguer entre les mois (sans aucune limite). En cliquant sur un jour, le système changera la date interne du jeu.

//=============================================================================
// Sphinx-SceneCalendar.js
//=============================================================================

/*:
 * @plugindesc Système Temps Réel - Scène de changement de date
 * @author Sphinx
 *
 * @help
 * Scène de réglage du jour fictif
 * 
 * Dépendances : - MomentJS et son extension Timezone (https://momentjs.com/)
 *               - Math.easing
 *               - Sphinx-GameClock
 * 
 * @param monthTitle
 * @text Arrière plan du mois
 * @type file
 * @default monthTitle
 * @dir img/calendar
 * @require 1
 * 
 * @param daysLabel
 * @text Arrière plan du nom du jour
 * @type file
 * @default 6E6E6E
 * @dir img/calendar
 * @require 1
 * 
 * @param days
 * @text Arrière plan d'un jour normal
 * @type file
 * @default 4DFFFF
 * @dir img/calendar
 * @require 1
 * 
 * @param currentDay
 * @text Arrière plan du jour courant
 * @type file
 * @default FF4000
 * @dir img/calendar
 * @require 1
 * 
 * @param daysOtherMonth
 * @text Arrière plan des jours des autres mois
 * @type file
 * @default D6D6C2
 * @dir img/calendar
 * @require 1
 * 
 * @param daysWeekEnd
 * @text Arrière plan des jours du week-end
 * @type file
 * @default 8080FF
 * @dir img/calendar
 * @require 1
 * 
 * @param daysHoliday
 * @text Arrière plan des jours fériés
 * @type file
 * @default FF9900
 * @dir img/calendar
 * @require 1
 */
Game_Interpreter.prototype.SphinxSceneCalendarPluginCommand = Game_Interpreter.prototype.pluginCommand;
Game_Interpreter.prototype.pluginCommand = function(command, args) {
    switch(command) {
        case "REGLER_CALENDRIER":
            SceneManager.push(Scene_Calendar);
            break;
        default:
            Game_Interpreter.prototype.SphinxSceneCalendarPluginCommand.call(this, command, args);
            break;
    }
};

ImageManager.loadCalendar = function(filename, hue) {
    return this.loadBitmap('img/calendar/', filename, hue, true);
};

Date.Easter = function(Y) {
    var f = Math.floor;
    // Golden Number - 1
    G = Y % 19;
    C = f(Y / 100);
    // related to Epact
    H = (C - f(C / 4) - f((8 * C + 13)/25) + 19 * G + 15) % 30;
    // number of days from 21 March to the Paschal full moon
    I = H - f(H/28) * (1 - f(29/(H + 1)) * f((21-G)/11));
    // weekday for the Paschal full moon
    J = (Y + f(Y / 4) + I + 2 - C + f(C / 4)) % 7;
    // number of days from 21 March to the Sunday on or before the Paschal full moon
    L = I - J;
    M = 3 + f((L + 40)/44);
    D = L + 28 - 31 * f(M / 4);
    easterDay = moment().year(Y).month(M - 1).date(D);
    return easterDay;
};

moment.prototype.isHoliday = function(year) {
    var holiday = [
        "01/01",
        "01/05",
        "08/05",
        "14/07",
        "15/08",
        "01/11",
        "11/11",
        "25/12",
    ]
    var easterDay = Date.Easter(parseInt(this.format("YYYY"), 10));
    var easterMonday = easterDay.clone().add(1, "day");
    var ascensionDay = easterDay.clone().add(40, "days");
    var pentecostDay = easterDay.clone().add(50, "day");
    holiday.push(easterDay.format("DD/MM"));
    holiday.push(easterMonday.format("DD/MM"));
    holiday.push(ascensionDay.format("DD/MM"));
    holiday.push(pentecostDay.format("DD/MM"));
    return holiday.includes(this.format("DD/MM"));
};

function Scene_Calendar() {
    this.initialize.apply(this, arguments);
};

Scene_Calendar.prototype = Object.create(Scene_Base.prototype);
Scene_Calendar.prototype.constructor = Scene_Calendar;

Scene_Calendar.prototype.initialize = function() {
    Scene_Base.prototype.initialize.call(this);
};

Scene_Calendar.prototype.create = function() {
    Scene_Base.prototype.create.call(this);
    this.date = $gameClock.getTime();
    this.monthTitleBitmap = ImageManager.loadCalendar(PluginManager.parameters('Sphinx-SceneCalendar')["monthTitle"]);
    this.daysLabelBitmap = ImageManager.loadCalendar(PluginManager.parameters('Sphinx-SceneCalendar')["daysLabel"]);
    this.daysBitmap = ImageManager.loadCalendar(PluginManager.parameters('Sphinx-SceneCalendar')["days"]);
    this.currentDayBitmap = ImageManager.loadCalendar(PluginManager.parameters('Sphinx-SceneCalendar')["currentDay"]);
    this.daysOtherMonthBitmap = ImageManager.loadCalendar(PluginManager.parameters('Sphinx-SceneCalendar')["daysOtherMonth"]);
    this.daysWeekEndBitmap = ImageManager.loadCalendar(PluginManager.parameters('Sphinx-SceneCalendar')["daysWeekEnd"]);
    this.daysHolidayBitmap = ImageManager.loadCalendar(PluginManager.parameters('Sphinx-SceneCalendar')["daysHoliday"]);
    this.createButtons();
    this.createMonthLabel();
    this.createDaysLabels();
};

Scene_Calendar.prototype.getTypeDay = function(date) {
    if(date.format("YYYY/MM/DD") == $gameClock.getTime().format("YYYY/MM/DD")) {
        return "current";
    }
    if(this.date.month() != date.month()) {
        return "otherMonth";
    }
    if(date.isHoliday()) {
        return "holiday";
    }
    if(date.format("dd") == "Sa" || date.format("dd") == "Di") {
        return "weekEnd";
    }
    return "day";
};

Scene_Calendar.prototype.createButtons = function() {
    var bitmap = ImageManager.loadSystem('ButtonSet');
    var buttonLeft = new Sprite_Button();
    buttonLeft.bitmap = bitmap;
    buttonLeft.setColdFrame(96, 0, 48, 48);
    buttonLeft.setHotFrame(96, 48, 48, 48);
    buttonLeft.anchor.x = 0.5;
    buttonLeft.anchor.y = 0.5;
    buttonLeft.rotation = 270 * Math.PI / 180;
    buttonLeft.x = 158;
    buttonLeft.y = 80;
    buttonLeft.setClickHandler((() => {
        this.date.subtract(1, "month");
        this.updateMonth = true;
    }).bind(this));
    this.addChild(buttonLeft);

    var buttonRight = new Sprite_Button();
    buttonRight.bitmap = bitmap;
    buttonRight.setColdFrame(48, 0, 48, 48);
    buttonRight.setHotFrame(48, 48, 48, 48);
    buttonRight.anchor.x = 0.5;
    buttonRight.anchor.y = 0.5;
    buttonRight.rotation = 270 * Math.PI / 180;
    buttonRight.x = 658;
    buttonRight.y = 80
    buttonRight.setClickHandler((() => {
        this.date.add(1, "month");
        this.updateMonth = true;
    }).bind(this));
    this.addChild(buttonRight);
};

Scene_Calendar.prototype.createMonthLabel = function() {
    this.monthTitle = new Sprite();
    this.monthTitle.anchor.x = 0.5;
    this.monthTitle.anchor.y = 0.5;
    this.monthTitle.x = 408;
    this.monthTitle.y = 80;
    this.addChild(this.monthTitle);
    this.updateMonth = true;
};

Scene_Calendar.prototype.createDaysLabels = function() {
    this.daysLabel = [];
    for(i = 0; i < DAYS_LABELS.length; ++i) {
        d = DAYS_LABELS[(i + 1) % 7];
        this.daysLabel[d] = new Sprite();
        this.daysLabel[d].anchor.x = 0.5;
        this.daysLabel[d].anchor.y = 0.5;
        this.daysLabel[d].x = 408 + (i - 3) * 70;
        this.daysLabel[d].y = 160;
        this.addChild(this.daysLabel[d]);
    }
    this.updateDaysLabels = true;
};

Scene_Calendar.prototype.start = function() {
    Scene_Base.prototype.start.call(this);
};

Scene_Calendar.prototype.update = function() {
    Scene_Base.prototype.update.call(this);
    if(this.updateMonth) {
        this.redrawMonthTitle();
        this.drawDays();
    }
    if(this.updateDaysLabels) {
        this.redrawDaysLabels();
    }
    this.updateExit();
};

Scene_Calendar.prototype.redrawMonthTitle = function() {
    this.monthTitle.bitmap = new Bitmap(400, 64);
    this.monthTitle.bitmap.blt(this.monthTitleBitmap, 0, 0, 400, 64, 0, 0);
    this.monthTitle.bitmap.fontSize = 48;
    this.monthTitle.bitmap.drawText(this.date.format("MMMM") + " " + this.date.year(), 0, 0, 400, 64, 'center');
    this.updateMonth = false;
};

Scene_Calendar.prototype.redrawDaysLabels = function() {
    for(i = 0; i < DAYS_LABELS.length; ++i) {
        d = DAYS_LABELS[(i + 1) % 7];
        this.daysLabel[d].bitmap = new Bitmap(70, 70);
        this.daysLabel[d].bitmap.blt(this.daysLabelBitmap, 0, 0, 70, 70, 0, 0);
        this.daysLabel[d].bitmap.fontSize = 24;
        this.daysLabel[d].bitmap.drawText(d, 10, 10, 50, 50, 'center');
    }
    this.updateDaysLabels = false;
};

Scene_Calendar.prototype.drawDays = function() {
    this.startMonth = this.date.clone().date(1);
    this.firstDay = this.startMonth.clone();
    while(this.firstDay.format("d") != "1") {
        this.firstDay.subtract(1, "day");
    }
    this.lastDay = this.startMonth.clone().add(1, "month").date(1);
    while(this.lastDay.format("d") != "0") {
        this.lastDay.add(1, "day");
    }
    var day = this.firstDay.clone();
    if(this.days) {
        for(var d of this.days) {
            this.removeChild(d);
        }
    }
    this.days = [];
    var weekMonth = 0;
    while(day.format("YYYY/MM/DD") <= this.lastDay.format("YYYY/MM/DD")) {
        var d = this.days.length;
        this.days[d] = new Sprite_Button();
        this.days[d].anchor.x = 0.5;
        this.days[d].anchor.y = 0.5;
        this.days[d].x = 408 + ((parseInt(day.format("d"), 10) + 6) % 7 - 3) * 70;
        this.days[d].y = 230 + weekMonth * 70;
        this.addChild(this.days[d]);
        this.days[d].bitmap = new Bitmap(70, 70);
        switch(this.getTypeDay(day)) {
            case "current":
                this.days[d].bitmap.blt(this.currentDayBitmap, 0, 0, 70, 70, 0, 0);
                break;
            case "holiday":
                this.days[d].bitmap.blt(this.daysHolidayBitmap, 0, 0, 70, 70, 0, 0);
                break;
            case "weekEnd":
                this.days[d].bitmap.blt(this.daysWeekEndBitmap, 0, 0, 70, 70, 0, 0);
                break;
            case "otherMonth":
                this.days[d].bitmap.blt(this.daysOtherMonthBitmap, 0, 0, 70, 70, 0, 0);
                break;
            case "day":
            default:
                this.days[d].bitmap.blt(this.daysBitmap, 0, 0, 70, 70, 0, 0);
                break;
        }
        this.days[d].bitmap.fontSize = 24;
        this.days[d].bitmap.drawText(day.format("D"), 10, 10, 50, 50, 'center');
        this.days[d].setClickHandler(((day) => {
            offset = day.hour(0).minutes(0).seconds(0).milliseconds(0) - $gameClock.getTime().hour(0).minutes(0).seconds(0).milliseconds(0);
            $gameClock.addGap(offset);
            this.updateMonth = true;
        }).bind(this, day.clone()));
        
        day = day.add(1, "day");
        if(day.format("d") == 1) {
            weekMonth++;
        }
    }
};

Scene_Calendar.prototype.updateExit = function() {
    if (this.isExitCalled()) {
        SceneManager.pop();
    }
};

Scene_Calendar.prototype.isExitCalled = function() {
    return Input.isTriggered('menu') || TouchInput.isCancelled();
};

Pour fonctionner, vous aurez besoin de ces images. Décompressez ce fichier zip dans le dossier img/ de votre projet : calendar.zip.

Sphinx-SceneClock

Maintenant on va passer à la scène de réglage de l’heure. Avec la commande de plugin REGLER_PENDULE, la scène de réglage de l’heure s’ouvrira et affichera une pendule, ainsi que de quoi la régler en dessous.

//=============================================================================
// Sphinx-SceneClock.js
//=============================================================================

/*:
 * @plugindesc Système Temps Réel - Scène de changement d'heure
 * @author Sphinx
 *
 * @help
 * Scène de réglage de l'heure fictive
 * 
 * Dépendances : - MomentJS et son extension Timezone (https://momentjs.com/)
 *               - Math.easing
 *               - Sphinx-GameClock
 * 
 * @param clockBack
 * @text Image horloge
 * @desc Image de l'horloge
 * @type file
 * @default Clock
 * @dir img/clock
 * @require 1
 * 
 * @param hourHand
 * @text Image aiguille heures
 * @desc Image de l'aiguille des heures
 * @type file
 * @default ClockHours
 * @dir img/clock
 * @require 1
 * 
 * @param hourMinutes
 * @text Image aiguille minutes
 * @desc Image de l'aiguille des minutes
 * @type file
 * @default ClockMinutes
 * @dir img/clock
 * @require 1
 * 
 * @param hourSeconds
 * @text Image aiguille secondes
 * @desc Image de l'aiguille des secondes
 * @type file
 * @default ClockSeconds
 * @dir img/clock
 * @require 1
 * 
 */
Game_Interpreter.prototype.SphinxSceneClockPluginCommand = Game_Interpreter.prototype.pluginCommand;
Game_Interpreter.prototype.pluginCommand = function(command, args) {
    switch(command) {
        case "REGLER_PENDULE":
            SceneManager.push(Scene_Clock);
            break;
        default:
            Game_Interpreter.prototype.SphinxSceneClockPluginCommand.call(this, command, args);
            break;
    }
};

ImageManager.loadClock = function(filename, hue) {
    return this.loadBitmap('img/clock/', filename, hue, true);
};

function Scene_Clock() {
    this.initialize.apply(this, arguments);
};

Scene_Clock.prototype = Object.create(Scene_Base.prototype);
Scene_Clock.prototype.constructor = Scene_Clock;

Scene_Clock.prototype.initialize = function() {
    Scene_Base.prototype.initialize.call(this);
};

Scene_Clock.prototype.create = function() {
    Scene_Base.prototype.create.call(this);
    this.createClock();
    this.createSprites();
    this.createButtons();
};

Scene_Clock.prototype.createClock = function() {
    var clockCenter = {
        x: 408,
        y: 222
    }
    this._clockSprite = new Sprite();
    this._clockSprite.bitmap = ImageManager.loadClock("Clock");
    this._clockSprite.anchor.x = 0.5;
    this._clockSprite.anchor.y = 0.5;
    this._clockSprite.x = clockCenter.x;
    this._clockSprite.y = clockCenter.y;
    this.addChild(this._clockSprite);
    
    this._clockSecondsSprite = new Sprite();
    this._clockSecondsSprite.bitmap = ImageManager.loadClock("ClockSeconds");
    this._clockSecondsSprite.anchor.x = 0.5;
    this._clockSecondsSprite.anchor.y = 0.83009708737864077669902912621359;
    this._clockSecondsSprite.x = clockCenter.x;
    this._clockSecondsSprite.y = clockCenter.y;
    this.addChild(this._clockSecondsSprite);
    
    this._clockMinutesSprite = new Sprite();
    this._clockMinutesSprite.bitmap = ImageManager.loadClock("ClockMinutes");
    this._clockMinutesSprite.anchor.x = 0.5;
    this._clockMinutesSprite.anchor.y = 0.84408602150537634408602150537634;
    this._clockMinutesSprite.x = clockCenter.x;
    this._clockMinutesSprite.y = clockCenter.y;
    this.addChild(this._clockMinutesSprite);
    
    this._clockHoursSprite = new Sprite();
    this._clockHoursSprite.bitmap = ImageManager.loadClock("ClockHours");
    this._clockHoursSprite.anchor.x = 0.5;
    this._clockHoursSprite.anchor.y = 0.78625954198473282442748091603053;
    this._clockHoursSprite.x = clockCenter.x;
    this._clockHoursSprite.y = clockCenter.y;
    this.addChild(this._clockHoursSprite);
};

Scene_Clock.prototype.createSprites = function() {
    this._sprites = [];
    for(var i = 0; i < 3; i++) {
        sprite = new Sprite();
        sprite.bitmap = new Bitmap(96, 48);
        sprite.bitmap.fontSize = 32;
        sprite.x = 204 + 180 * i;
        sprite.y = 494;
        this._sprites.push(sprite);
        this.addChild(sprite);
    }
};

Scene_Clock.prototype.createButtons = function() {
    var bitmap = ImageManager.loadSystem('ButtonSet');
    var gap = [ 3600000, 60000, 1000 ];
    for(var i = 0; i < 3; i++) {
        var buttonTop = new Sprite_Button();
        buttonTop.bitmap = bitmap;
        buttonTop.setColdFrame(96, 0, 48, 48);
        buttonTop.setHotFrame(96, 48, 48, 48);
        buttonTop.anchor.x = 0.5;
        buttonTop.anchor.y = 0.5;
        buttonTop.x = 228 + 180 * i;
        buttonTop.y = 456;
        buttonTop.setClickHandler($gameClock.addGap.bind($gameClock, gap[i]));
        this.addChild(buttonTop);
        
        var buttonBottom = new Sprite_Button();
        buttonBottom.bitmap = bitmap;
        buttonBottom.setColdFrame(48, 0, 48, 48);
        buttonBottom.setHotFrame(48, 48, 48, 48);
        buttonBottom.anchor.x = 0.5;
        buttonBottom.anchor.y = 0.5;
        buttonBottom.x = 228 + 180 * i;
        buttonBottom.y = 580;
        buttonBottom.setClickHandler($gameClock.subtractGap.bind($gameClock, gap[i]));
        this.addChild(buttonBottom);
    }
};

Scene_Clock.prototype.start = function() {
    Scene_Base.prototype.start.call(this);
};

Scene_Clock.prototype.update = function() {
    Scene_Base.prototype.update.call(this);
    this.updateClock();
    this.updateSprites();
    this.updateExit();
};

Scene_Clock.prototype.updateClock = function() {
    var date = $gameClock.getTime();
    this._clockSecondsSprite.rotation = parseInt(date.format("s"), 10) * 360 / 60 * Math.PI / 180;
    this._clockMinutesSprite.rotation = (parseInt(date.format("m"), 10) * 360 / 60 + parseInt(date.format("s"), 10) * 360 / 3600) * Math.PI / 180;
    this._clockHoursSprite.rotation = (parseInt(date.format("H"), 10) * 360 / 12 + parseInt(date.format("m"), 10) * 360 / 720 + parseInt(date.format("s"), 10) * 360 / 43200) * Math.PI / 180;
};

Scene_Clock.prototype.updateSprites = function() {
    var date = $gameClock.getTime();
    var hour = [ date.format("HH"), date.format("mm"), date.format("ss") ];
    for(var i = 0; i < 3; ++i) {
        this._sprites[i].bitmap.clear();
        this._sprites[i].bitmap.drawText(hour[i], 0, 0, 48, 48, 'center');
    }
};

Scene_Clock.prototype.updateExit = function() {
    if (this.isExitCalled()) {
        SceneManager.pop();
    }
};

Scene_Clock.prototype.isExitCalled = function() {
    return Input.isTriggered('menu') || TouchInput.isCancelled();
};

Pour fonctionner, vous aurez besoin de ces images. Décompressez ce fichier zip dans le dossier img/ de votre projet : clock.zip.

Et voilà, vous avez tout. Enjoy it !

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

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