#=============================================================================== # # # Mto_Sun.v3 # # #=============================================================================== # #by Vincentmhd, #http://vincentmhdmaker.canalblog.com/ #v1 -> v2 Les rayon peuvent maintenant faire le tour complet de l'écran #v2 -> v3 Correction de la méthode Stop # Ajustement de la longueur des rayons en fonction de la distance du soleil possible # Meilleure gestion de l'intensité #=====================================NOTE====================================== =begin
Ce script est un script Météorologique. Il permet d'appeler le Soleil, comme on appelle la pluie, ou la neige.
Le soleil est composé de rayon qui suivent leur propre cycle. Ils apparaissent, restent, disparaissent, attendant, pour réapparaitre et ainsi de suite. A chaque réapparition ils changent de place, forme.
La position du Soleil se détermine par l'heure (et les minutes) appel par la méthode: $sun.position(heure,minutes)
Pour appeler le Soleil: $sun.play(Intensité, Temps_d'_apparition)
Pour arrêter la météo: $sun.stop(temps_de_disparition)
Pour changer l'opacité de tout les rayons à la fois momentanément $sun.change_opacity(opacity, duration =0)
Le tout est assez customisable dans le module ci-dessous.
=end #-------------------------------------------------------------------------------
module Mhd_Sun #=============================================================================== # Rayons #=============================================================================== #Images et Sprites LONGUEUR_MAX = 500 LONGUEUR_MIN = 300
HAUTEUR_MAX = 30 HAUTEUR_MIN = 5 CALCUL_DISTANCE = true #détermine s'il l'on prend en compte la distance écran<->soleil #dans le calcul de la longueur des rayons VARIANCE_ANGLE = 30 #Delta des angles des rayons ALPHA_RAYON = 2*255/3 #Alpha des images de bases
OPACITY_MAX = 255 #Min et max de l'opacité des OPACITY_MIN = 255/2 #Sprites des rayons #Durées des Cycles:: Durées #Transition_naturelle DUREE_APP_MAX = 120 DUREE_APP_MIN = 60
#Attend WAIT_MAX = 60 WAIT_MIN = 5
#Lumine SOLEIL_MAX = 160 SOLEIL_MIN = 60
#=============================================================================== # Soleil #=============================================================================== HEURE_DEFAULT = 14 #Pris si rien n'est spécifié MINUTE_DEFAULT = 0
CHANGE_DUREE = 60 #Durée moyenne de changement d'opacité général par défaut CHANCE_CHANGE = 5000 #Chance sur 1 d'avoir un changement d'opacité général #à la frame
DISTANCE_SOLEIL = 550 #Rayon de rotation X_ORIGINE = 416/2 #Axe de rotation Y_ORIGINE = 544/2 #Axe de rotation
TETA_MIN = 25 #Angle parcourru à l'écran (par rapport à la droite y = Y_ORIGINE) TETA_MAX = 155 #Angle parcourru à l'écran (par rapoort à la droite y = Y_ORIGINE) HEURE_MIN = 8 #A Heure_min, Téta = Téta_min MINUTE_MIN = 15 #60 min = 1h 0 min donc 60 n'existe pas! HEURE_MAX = 19 #A Heure_max, Téta = Téta_max MINUTE_MAX = 15 NBS_RAYONS_MIN = 5 NBS_RAYONS_MAX = 15 #ne correspond pas au vrai max et min (+ ou - 20%) #=============================================================================== # Influences Mutuelles #=============================================================================== RONDEUR = 90 #avec le placement des sprites sur les #contours et non directement au soleil #on perd la rondeur de celui-ci la rondeur #est un correctif fonction de la variance #angulaire et de l'angle avec l'axe #Soleil/centre de rotation INFLUENCE_H = 90 #représente l'influence du pourcentage #horaire du soleil sur la dimension #des rayons: au zénith les rayons sont à #100% de leur longueur possible. Au #crépuscule et à l'aube, ils sont au #minimun à LONGUEUR_MIN*(1-INFLUENCE_H/100) end
#=============================================================================== # # # Petits utilitaires # # #===============================================================================
module Mhd_Math #convertir en radians def put_in_rad(angle) return angle = ((Math::PI.to_f * angle.to_f) /180) end #plus ou moins X% def plus_ou_moins(nombre, pourcentage) pourcentage = (100 - pourcentage) + rand( pourcentage*2 ) pourcentage = pourcentage.to_f/100 nombre = nombre.to_f * pourcentage return nombre end end #Inclusion dans l'espace commun include Mhd_Math
#=============================================================================== # Ajout aux couleurs #===============================================================================
class Color def moyenne_avec(color) self.red = (self.red + color.red) / 2 self.green = (self.green + color.green) / 2 self.blue = (self.blue + color.blue) / 2 self.alpha = (self.alpha + color.alpha) / 2 end end
#============================================================================== # Ajout aux Bitmap #==============================================================================
class Bitmap def moyenne_avec(bitmap) for x in 0...self.width for y in 0...self.height couleur = self.get_pixel(x,y) couleur.moyenne_avec(bitmap.get_pixel(x,y)) self.set_pixel(x,y,couleur) end end end def gradient_param(colorA, colorB, param) return ((1-param)*colorA.to_f + (param)*colorB.to_f).to_i end def gradient_color(colorA, colorB, param) r= gradient_param(colorA.red, colorB.red, param) g= gradient_param(colorA.green, colorB.green, param) b= gradient_param(colorA.blue, colorB.blue, param) a= gradient_param(colorA.alpha, colorB.alpha, param) return Color.new(r,g,b,a) end def mhd_gradient_A(couleur_B, rect = self.rect) for x in 0...rect.width for y in 0...rect.height couleur_A = self.get_pixel(x + rect.x, y + rect.y) param = ((rect.width.to_f - x.to_f)*(y.to_f))/(rect.width.to_f * rect.height.to_f) couleur_C = gradient_color(couleur_A, couleur_B, param) self.set_pixel(x + rect.x, y + rect.y, couleur_C) end end end
def mhd_gradient_B(couleur_B, rect = self.rect) for x in 0...rect.width for y in 0...rect.height couleur_A = self.get_pixel(x + rect.x,y + rect.y) param = ((rect.width.to_f - x.to_f)*(rect.height.to_f - y.to_f))/(rect.width.to_f * rect.height.to_f) couleur_C = gradient_color(couleur_A, couleur_B, param) self.set_pixel(x + rect.x, y + rect.y, couleur_C) end end end def mhd_gradient_C(couleur_B, rect = self.rect) for y in 0...rect.height for x in 0...rect.width couleur_A = self.get_pixel(x + rect.x, y + rect.y) param = ((rect.height.to_f - y.to_f)*(x.to_f))/(rect.width.to_f * rect.height.to_f) couleur_C = gradient_color(couleur_A, couleur_B, param) self.set_pixel(x + rect.x, y + rect.y, couleur_C) end end end def mhd_gradient_D(couleur_B, rect = self.rect) for y in 0...rect.height for x in 0...rect.width couleur_A = self.get_pixel(x + rect.x,y + rect.y) param = ((rect.width.to_f - x.to_f)*(rect.height.to_f - y.to_f))/(rect.width.to_f * rect.height.to_f) couleur_C = gradient_color(couleur_A, couleur_B, param) self.set_pixel(x + rect.x, y + rect.y, couleur_C) end end end #=============================================================================== # Dessine des Rayons #=============================================================================== def draw_rayon_A self.fill_rect(self.rect, Color.new(255,255,255,0)) self.mhd_gradient_A(Color.new(255,255,255,Mhd_Sun::ALPHA_RAYON),Rect.new(0, 0, self.width, self.height/2) ) self.mhd_gradient_B(Color.new(255,255,255,Mhd_Sun::ALPHA_RAYON),Rect.new(0, self.height/2, self.width, self.height - self.height/2) ) end def draw_rayon_B self.fill_rect(self.rect, Color.new(255,255,255,0)) self.mhd_gradient_C(Color.new(255,255,255,Mhd_Sun::ALPHA_RAYON),Rect.new(0, 0, self.width/2, self.height) ) self.mhd_gradient_D(Color.new(255,255,255,Mhd_Sun::ALPHA_RAYON),Rect.new(self.width/2, 0, self.width - self.width/2, self.height) ) end end
#=============================================================================== # # # Les rayons # # #===============================================================================
class Rayon
def initialize(soleil_x, soleil_y, soleil_teta, intensity, pourcentage_horraire) physical_data(pourcentage_horraire, intensity) creer_sprite(soleil_x, soleil_y, soleil_teta) clear_timer end def physical_data(pourcentage_horraire, intensity) @distance = 0 @pourcentage = pourcentage_horraire @intensity = intensity @opacity = Mhd_Sun::OPACITY_MIN + ((@intensity.to_f/10)*(Mhd_Sun::OPACITY_MAX.to_f - Mhd_Sun::OPACITY_MIN.to_f) ) @opacity = (Mhd_Math.plus_ou_moins( @opacity, 20)).to_i end def clear_timer @fade = false @duree = 0 @transition = 0 @wait = Mhd_Sun::WAIT_MIN + rand(Mhd_Sun::WAIT_MAX - Mhd_Sun::WAIT_MIN) @soleil = 0 end #=============================================================================== # La Sprite... #=============================================================================== #Créer la sprite, et les données physiques def creer_sprite(soleil_x, soleil_y, teta) @sprite = Sprite.new() @sprite.opacity = 0 if ((@pourcentage <= 1.0) && (@pourcentage >= 0.0)) position(soleil_x, soleil_y, teta) else @sprite.dispose end end #regroupe les méthodes physiques def position(soleil_x, soleil_y, soleil_teta) if !(@sprite.disposed?) calcul_angle(soleil_teta) calcul_coord(soleil_x, soleil_y, @angle) choix_bitmap end end
#=============================================================================== # L'angle #=============================================================================== #Calcul l'angle du rayon en fonction de la position du soleil dans sa #trajectoire cela se manifeste en tout premier par son angle def calcul_angle(teta) if !(@sprite.disposed?) angle = 180 - teta delta = rand(Mhd_Sun::VARIANCE_ANGLE) if rand(2)>= 1 angle += delta else angle -= delta end @angle = angle #calcul rondeur @rondeur = (1 - Mhd_Sun::RONDEUR.to_f/100) + (Mhd_Sun::RONDEUR.to_f/100)*(1 - delta.to_f/(Mhd_Sun::VARIANCE_ANGLE.to_f)) end end #=============================================================================== # Les coordonnées #=============================================================================== def calcul_coord(soleil_x, soleil_y, rayon_teta) if !(@sprite.disposed?) rayon_teta = put_in_rad(rayon_teta) b = (soleil_y.to_f + soleil_x.to_f * Math.tan(rayon_teta)) a = (b - soleil_y.to_f)/( - soleil_x.to_f) i=[] j=[] k=[] l=[] i[0] = 0.0 i[1] = b j[0] = -b/a j[1] = 0.0 k[0] = 544.0 k[1] = 544.0*a +b l[0] = (416.0 -b )/a l[1] = 416.0 tab = [i,j,k,l] id = nil distance = nil for n in 0...tab.size() if ( (tab[n][1] >= 0) && (tab[n][1]<= 416) && (tab[n][0] >= 0) && (tab[n][0]<= 544) ) d = Math.sqrt((tab[n][1]-soleil_y)*(tab[n][1]-soleil_y) + (tab[n][0]-soleil_x)*(tab[n][0]-soleil_x)) if distance == nil distance = d id = n else if distance > d distance = d id = n end end end end if !(id == nil) @distance = distance @sprite.x = tab[id][0] @sprite.y = tab[id][1] else @sprite.dispose end end end #=============================================================================== # Choix de l'image #=============================================================================== #Selon les coordonées et l'angle du rayon, il ne va prendre la même image pour #masquer les coins de ces dernières. def choix_bitmap if !(@sprite.disposed?) angle = @angle
#Condition permettant de connaitre le côté de l'apparition a = ( (angle >= -90) && (angle <= 0) && !(!(@sprite.y == 0)) ) b = ( (angle >= 0) && (angle <= 90) && !(!(@sprite.x == 0)) ) c = ( (angle >= 90) && (angle <= 180) && !(!(@sprite.y == 416)) ) d = ( (angle >= -180) && (angle <= -90) && !(!(@sprite.x == 544)) )
#Proportion des rayon en fonction du pourcentage horraire if(@pourcentage >0.5 ) proportion = 2*(1 - @pourcentage) else proportion = @pourcentage end proportion = (1 - Mhd_Sun::INFLUENCE_H.to_f/100) + ((Mhd_Sun::INFLUENCE_H.to_f/100) * proportion )
if (a||b||c||d) #Rayon de type B angle += 90 #angle à ré-adapter @sprite.bitmap = $mhd_ray_B longueur = Mhd_Sun::HAUTEUR_MIN + ((@intensity.to_f/10)*(Mhd_Sun::HAUTEUR_MAX.to_f - Mhd_Sun::HAUTEUR_MIN.to_f)) longueur = (Mhd_Math.plus_ou_moins( longueur , 20)).to_i hauteur = Mhd_Sun::LONGUEUR_MIN + ((@intensity.to_f/10)*(Mhd_Sun::LONGUEUR_MAX.to_f - Mhd_Sun::LONGUEUR_MIN.to_f)) hauteur = (Mhd_Math.plus_ou_moins( hauteur , 20)).to_i if Mhd_Sun::CALCUL_DISTANCE == true #longueur *= (hauteur - @distance) /hauteur hauteur -= @distance end longueur *= proportion hauteur *= proportion *@rondeur @sprite.zoom_x = (longueur.to_f/Mhd_Sun::HAUTEUR_MAX.to_f) @sprite.zoom_y = (hauteur.to_f/Mhd_Sun::LONGUEUR_MAX.to_f) else @sprite.bitmap = $mhd_ray_A longueur = Mhd_Sun::LONGUEUR_MIN + ((@intensity.to_f/10)*(Mhd_Sun::LONGUEUR_MAX.to_f - Mhd_Sun::LONGUEUR_MIN.to_f)) longueur = (Mhd_Math.plus_ou_moins( longueur , 20)).to_i hauteur = Mhd_Sun::HAUTEUR_MIN + ((@intensity.to_f/10)*(Mhd_Sun::HAUTEUR_MAX.to_f - Mhd_Sun::HAUTEUR_MIN.to_f)) hauteur = (Mhd_Math.plus_ou_moins( hauteur , 20)).to_i if Mhd_Sun::CALCUL_DISTANCE == true #hauteur *= (longueur - @distance) / longueur longueur -= @distance end longueur *= proportion *@rondeur hauteur *= proportion @sprite.zoom_x = (longueur.to_f/Mhd_Sun::LONGUEUR_MAX.to_f) @sprite.zoom_y = (hauteur.to_f/Mhd_Sun::HAUTEUR_MAX .to_f) end @sprite.angle = angle if ((longueur <= 0 )||( hauteur <= 0)) @sprite.dispose end end end #=============================================================================== # Actions #=============================================================================== #Change l'opacité (indépendanment de fade-in et fade_out) def change_opacity( opacity, transition) @target_opacity = opacity @transition = transition if (transition == 0 && (!(@sprite.disposed?))) @sprite.opacity = @target_opacity end end #Force le rayon à s'éteindre def fade_out(time) @wait = 0 @transition = 0 @duree = - time @soleil = 0 @fade = true end
#=============================================================================== # Cycle du Rayon #=============================================================================== def cycle_update(soleil_x, soleil_y, teta) #En suspend en cas de transition if @transition == 0 #Apparition if @duree > 0 d = @duree if !(@sprite.disposed?) @sprite.opacity = (@sprite.opacity * (d - 1) + @opacity) / d end @duree -= 1 if @duree == 0 @soleil = Mhd_Sun::SOLEIL_MIN + rand(Mhd_Sun::SOLEIL_MAX - Mhd_Sun::SOLEIL_MIN) end end #Brille if @soleil >0 @soleil -=1 if @soleil == 0 @duree = -(Mhd_Sun::DUREE_APP_MIN + rand(Mhd_Sun::DUREE_APP_MAX - Mhd_Sun::DUREE_APP_MIN)) end end #Disparition if @duree < 0 d = -@duree if !(@sprite.disposed?) @sprite.opacity = (@sprite.opacity * (d - 1) + 0) / d end @duree += 1 if (@duree == 0)&&(@wait >= 0) if @fade == true @wait=-1 else @wait = Mhd_Sun::WAIT_MIN + (((10 - @intensity.to_f)/10)*(Mhd_Sun::WAIT_MAX.to_f - Mhd_Sun::WAIT_MIN.to_f)) @wait = (Mhd_Math.plus_ou_moins( @wait , 20)).to_i end @sprite.dispose end end #Attend if @wait >0 @wait -= 1 if @wait == 0 @opacity = Mhd_Sun::OPACITY_MIN + ((@intensity.to_f/10)*(Mhd_Sun::OPACITY_MAX.to_f - Mhd_Sun::OPACITY_MIN.to_f) ) @opacity = (Mhd_Math.plus_ou_moins( @opacity, 20)).to_i creer_sprite(soleil_x, soleil_y, teta) @duree = Mhd_Sun::DUREE_APP_MIN + rand(Mhd_Sun::DUREE_APP_MAX - Mhd_Sun::DUREE_APP_MIN) end end end end
#=============================================================================== # Update #=============================================================================== def update(soleil_x, soleil_y, teta, pourcentage) @pourcentage = pourcentage update_change_opacity cycle_update(soleil_x, soleil_y, teta) end
def update_change_opacity if @transition > 0 if !(@sprite.disposed?) d = @transition @sprite.opacity = (@sprite.opacity * (d - 1) + @target_opacity) / d end @transition -= 1 if (@transition == 0) if (@duree > 0) @duree = (Mhd_Sun::DUREE_APP_MIN + rand(Mhd_Sun::DUREE_APP_MAX - Mhd_Sun::DUREE_APP_MIN)) else if (@duree < 0) @duree = -(Mhd_Sun::DUREE_APP_MIN + rand(Mhd_Sun::DUREE_APP_MAX - Mhd_Sun::DUREE_APP_MIN)) end end end end end end
#=============================================================================== # # # Le Soleil # # #=============================================================================== class Mto_Sun def initialize @play = false @chance = Mhd_Sun::CHANCE_CHANGE @stop_time = -1 @x = 0 @y = 0 @teta = 0 @change_count = 0 @change_target = 0 horaires() angles () position() end #=============================================================================== # Petits Paramètres #=============================================================================== def Nombre_rayons? @nbs_rayon = Mhd_Sun::NBS_RAYONS_MIN + ((@intensity.to_f/10)*(Mhd_Sun::NBS_RAYONS_MAX-Mhd_Sun::NBS_RAYONS_MIN).to_f).to_i @nbs_rayon = (Mhd_Math.plus_ou_moins(@nbs_rayon, 25)).to_i end #Definie les heures du jour (correspondance angles/heures adaptable) def horaires(heure_min = Mhd_Sun::HEURE_MIN, minute_min = Mhd_Sun::MINUTE_MIN, heure_max = Mhd_Sun::HEURE_MAX, minute_max = Mhd_Sun::MINUTE_MAX) @total_min = (60*heure_min) + minute_min @total_max = (60*heure_max) + minute_max end #Definie les angle min et max (correspondance angles/heures adaptable) def angles(angle_min = Mhd_Sun::TETA_MIN, angle_max = Mhd_Sun::TETA_MAX) @angle_min = (360 - angle_min.to_f) @angle_max = (360 - angle_max.to_f) end #Calcul du pourcentage horaire def pourcentage_horaire(heure, minute) total = heure * 60 + minute @pourcentage = (total.to_f - @total_min.to_f)/(@total_max.to_f - @total_min.to_f) end def size? print(@nbs_rayon) end #=============================================================================== # Actions #=============================================================================== #Active def play(intensite, apparition) if(@play == false) @soleil = [] @play = true @time = apparition @intensity = intensite @stop_time = -1 Nombre_rayons? create_rayon end end #Désactive def stop(time = 0) if @play == true @change_count = 0 @stop_time = time + 60 for i in 0...@soleil.size() @soleil[i].fade_out(time) end end end #Calcul la position du Soleil def position(heure = Mhd_Sun::HEURE_DEFAULT, minute = Mhd_Sun::MINUTE_DEFAULT) pourcentage_horaire(heure, minute) @teta = (@angle_max - @angle_min)*(@pourcentage) + @angle_min @x = (Mhd_Sun::X_ORIGINE.to_f + (Mhd_Sun::DISTANCE_SOLEIL.to_f)*( Math.cos(((Math::PI * @teta) /180)) )) @y = (Mhd_Sun::Y_ORIGINE.to_f + (Mhd_Sun::DISTANCE_SOLEIL.to_f)*( Math.sin(((Math::PI * @teta) /180)) )) end #Change toutes les opacités def change_opacity(opacity, time = Mhd_Sun::CHANGE_DUREE) @change_target = opacity @change_count = time for i in 0...@soleil.size() @soleil[i].change_opacity(opacity, time) end end
#=============================================================================== # Update #=============================================================================== def create_rayon for i in 0...@nbs_rayon @soleil += [Rayon.new(@x, @y, @teta, @intensity, @pourcentage)] end end def update stop_count if @play update_change for i in 0...@soleil.size() @soleil[i].update(@x, @y, @teta, @pourcentage) end end end def stop_count if @stop_time > 0 @stop_time -= 1 if @stop_time == 0 @play = false @stop_time = -1 end end end def stopping? if @stop_time > 0 return true else return false end end def update_change #un seul changement par défaut à la fois if !(stopping?) if @change_count == 0 a = rand(@chance) if a == @chance/2 opacity = (@intensity.to_f)*255/10 opacity = (Mhd_Math.plus_ou_moins( opacity, 25)).to_i duree = Mhd_Sun::CHANGE_DUREE/2 + rand(Mhd_Sun::CHANGE_DUREE) change_opacity(opacity , duree) end else @change_count -= 1 end end end
end
#==============================================================================# # # # Création de la Météo et des images # # # #==============================================================================# class Scene_Title alias mhd_sun_create_game_objects create_game_objects def create_game_objects mhd_sun_create_game_objects #horrizontal $mhd_ray_A = Bitmap.new(Mhd_Sun::LONGUEUR_MAX, Mhd_Sun::HAUTEUR_MAX) $mhd_ray_A.draw_rayon_A #vertical $mhd_ray_B = Bitmap.new(Mhd_Sun::HAUTEUR_MAX, Mhd_Sun::LONGUEUR_MAX) $mhd_ray_B.draw_rayon_B $sun = Mto_Sun.new end end
class Scene_Map alias vincentmhd_sun_update update def update vincentmhd_sun_update $sun.update end end |