Maire Lv.9
Age : 34 Inscrit le : 15/10/2008 Messages : 351
| Sujet: [VX] Déplacement et sélection à la souris Jeu 31 Déc 2009 - 15:40 | |
| Bonjour à tous, Pour conclure cette si belle année, voici une seconde mouture de mon script de déplacement à la souris. J'ai eu beaucoup de demandes de mise à jour. Après pas mal de temps, j'ai pris mon courage à deux mains et j'ai entièrement recodé le systeme. Globalement il est plus stable, plus rapide, mais aussi beaucoup plus complexe. Le contraire serait beaucoup moins drole. Quoi de neuf? - Nouvelle gestion du drag and drop par multithreading. Pour ceux à qui ca ne dit rien, c'est une sorte d'exécution parallèle de bouts de code. Bref, le résultat est plus rapide, mais le jeu est poussé à fond. Mais vous commencez à avoir l'habitude, après le calcul du système de brouillard de guerre. - Maintenant, tous les événements sélectionnés se déplacent. Sauf pour des sélections trop grandes: le script de pathfinding (le meilleur actuellement, de Modern Algebra) est ce qu'il est, il ne réfléchit pas trop longtemps. C'est peut être la seule ombre au script. Mais on ne peut rien y faire. - Les événements sélectionnés changent de couleur. - Les bordure de l'écran sont réactives, comme dans Age Of Empires, il suffit de mettre sa souris sur un coté, pour faire défiler la carte. - Mise en mémoire de la sélection d'événements jusqu'à nouvelle selection ou déselection. - Voila tout, je pense. Si vous avez des suggestions, n'hésitez pas. Voici en tout 4 scripts. A coller dans l'ordre suivant: - Citation :
- Clavier
Souris ... tous les scripts PathFinding Déplacement ... main Clavier - Spoiler:
- Code:
-
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # Gestion du Clavier # par TLN et Lordrik, revu par Berka rgss2 (VX) #-------------------------------------------------------------------------------------------------------------------------------------- # A placer au début de la liste de scripts, complètement. Ne pas utiliser deux scripts de clavier ! #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
module Win32API::APIS GAKS=Win32API.new("user32","GetAsyncKeyState",'i','i') GKS=Win32API.new("user32","GetKeyState",'i','i') KBDE=Win32API.new('user32','keybd_event','iii','') end include Win32API::APIS module Input class<<self Inconnu="Cette touche est inconnue" TAB_KEY={'clic gauche'=>1,'clic droit'=>2,'clic milieu'=>4, 'sm'=>4,'del'=>8,'tab'=>9,'enter'=>13,'shift'=>16,'ctrl'=>17,'alt'=>18, 'pause'=>19,'caps lock'=>20,'esc'=>27,'space'=>32,'pg up'=>33,'pg down'=>34, 'end'=>35,'home'=>36,'left'=>37,'up'=>38,'right'=>39,'down'=>40,'impr'=>44, 'insert'=>45,'suppr'=>46,'à'=>48,'&'=>49,'é'=>50,'"'=>51,"'"=>52,'('=>53, '-'=>54,'è'=>55,'_'=>56,'ç'=>57,'a'=>65,'b'=>66,'c'=>67,'d'=>68,'e'=>69, 'f'=>70,'g'=>71,'h'=>72,'i'=>73,'j'=>74,'k'=>75,'l'=>76,'m'=>77,'n'=>78, 'o'=>79,'p'=>80,'q'=>81,'r'=>82,'s'=>83,'t'=>84,'u'=>85,'v'=>86,'w'=>87, 'x'=>88,'y'=>89,'z'=>90,'lwin'=>91,'rwin'=>92,'fn'=>93,'altgr'=>95,'0'=>96, '1'=>97,'2'=>98,'3'=>99,'4'=>100,'5'=>101,'6'=>102,'7'=>103,'8'=>104, '9'=>105,'n*'=>106,'+'=>107,'num'=>108,'n-'=>109,'.'=>110,'/'=>111, 'F1'=>112,'F2'=>113,'F3'=>114,'F4'=>115,'F5'=>116,'F6'=>117,'F7'=>118, 'F8'=>119,'F9'=>120,'F10'=>121,'F11'=>122,'F12'=>123,'vernum'=>144, 'verdefil'=>145,'lmaj'=>160,'rmaj'=>161,'lctrl'=>162,'rctrl'=>163, 'lalt'=>164,'ralt'=>165,'$'=>186,'='=>187,','=>188,';'=>190,':'=>191, 'ù'=>192,')'=>219,'*'=>220,'^'=>221,'²'=>222,'!'=>223,'<'=>226} RS=TAB_KEY.clone RS.keys.each{|k|RS[k]=[false,false,10]} Dirs=['left','up','right','down'] alias :in_upd :update alias :in_trig? :trigger? # Berka: Compatibilité avec touches initiales alias :in_pres? :press? alias :in_rep? :repeat? def press?(n);n.is_a?(Integer)? in_pres?(n): RS[n][0];end def trigger?(n);n.is_a?(Integer)? in_trig?(n): RS[n][1]==1;end def dbtrigger?(n);RS[n][1]==2;end def repeat?(n);n.is_a?(Integer) ? in_rep?(n) : (RS[k][2]%=4;RS[n][2]==0&&RS[n][0]);end def hold?(n);((RS[n][2]%20)==0)&&RS[n][0];end def release?(n);RS[k][1]==-1;end def active?(n);GKS.call(TAB_KEY[k])&1==1;end def update(*tab) in_upd() if !tab.empty? tab.each{|n|m=RS[n][0];pr=GAKS.call(TAB_KEY[n])!=0 tr=m==pr ? 0 : (pr ?(RS[n][2].between?(1,9)? 2 : 1) : -1) count=tr>0 ? 0 : [R[n][2]+1,20].min RS[n]=[pr,tr,count]} else TAB_KEY.keys.each{|n| m=RS[n][0];pr=GAKS.call(TAB_KEY[n])!=0 tr=m==pr ? 0 : (pr ?(RS[n][2].between?(1,9)? 2 : 1) : -1) count=tr>0 ? 0 : [RS[n][2]+1,20].min RS[n]=[pr,tr,count]} end end end end Souris- Spoiler:
- Code:
-
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # Gestion de la Souris # par Cybersam et Nearfantastica, revu par Berka rgss2 (VX) #-------------------------------------------------------------------------------------------------------------------------------------- # A placer au début de la liste de scripts, juste après le script de Clavier #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
module Win32API::APIS GPPS=Win32API.new('kernel32','GetPrivateProfileString','pppplp','l') GCPr=Win32API.new('kernel32','GetCurrentProcess','','i') FW=Win32API.new('user32','FindWindow','pp','i') SPC=Win32API.new('kernel32','SetPriorityClass','pi','i') STC=Win32API.new('user32','ScreenToClient','lp','i') GTR=Win32API.new('user32','GetClientRect','lp','i') GCP=Win32API.new('user32','GetCursorPos','p','i') SC=Win32API.new('user32','ShowCursor','l','l') module_function def getini(s) GPPS.call("Game",s,"",v="\0"*0xff,0xff,".//Game.ini") v.delete!("\0") end Handle=FW.call("RGSS Player",getini("Title")) SPC.call(GCPr.call,128) end include Win32API::APIS class Souris attr_accessor :x,:y,:curseur def initialize @t||={};@curseur=Sprite.new;@curseur.z=9999 show;update end def update @x,@y=client(*pos_glob) width,height=t_client @x=0 if @x<0;@y=0 if @y<0 @x=width if x>width;@y=height if @y>height [@x,@y] end def show(b=false);@curseur.visible=!b;SC.call(b ? 1 : 0);end def in?(x,y,w,h);return false if @x.nil?||@y.nil?;@x.between?(x,x+w)&&@y.between?(y,y+h);end def pos_glob;p=[0,0].pack('ll');(GCP.call(p)!=0)? p.unpack('ll'): nil;end def client(x,y);return nil unless x&&y;p=[x,y].pack('ll');(STC.call(Handle,p)!=0)? p.unpack('ll'): nil;end def t_client;GTR.call(Handle,r=([0]*4).pack('l4'));r.unpack('l4')[2..3];end def grid;[(@x+$game_map.display_x/8)/32,(@y+$game_map.display_y/8)/32];end def drag(t,obj,&block) # Berka return if @t[t].alive? rescue nil @t[t]=Thread.new{ox,oy=@x,@y while Input.press?(t) ((nx=@x)-ox>0)?(x1=ox;x2=nx-x1):(x1=nx;x2=ox-x1) ((ny=@y)-oy>0)?(y1=oy;y2=ny-y1):(y1=ny;y2=oy-y1) obj.x,obj.y,obj.width,obj.height=x1,y1,x2,y2 Graphics.update yield end obj.visible=false} end def drag_orig(t,x,y) # Berka @b_x||=@x-x;@b_y||=@y-y (@x-@b_x>0)?(x2=@x-@b_x):(x2=-(@b_x-@x)) (@y-@b_y>0)?(y2=@y-@b_y):(y2=-(@b_y-@y)) [x2,y2] end def shcurseur(*c) # Berka @curseur.bitmap=Cache.system(c.first) @curseur.ox,@curseur.oy=*c[1..2] rescue @curseur.bitmap=Bitmap.new(24,24) @curseur.bitmap.blt(0,0,Cache.system("Iconset"),Rect.new(24,0,24,24)) @curseur.ox,@curseur.oy=8,8 end end $souris||=Souris.new module Graphics # Berka class<<self alias :cur_update :update unless $@ def update ($souris.curseur.x,$souris.curseur.y=*$souris.update)if $souris cur_update end end end
Pathfinding - Spoiler:
- Code:
-
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # Pathfinding # par Modern Algebra rgss2 (VX) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
class Game_System attr_accessor :pathfinding_diagonal,:pathfinding_iterations alias modalg_pathfinding_options_init_j5yt initialize def initialize modalg_pathfinding_options_init_j5yt @pathfinding_diagonal,@pathfinding_iterations=false,0 end end class Game_Character def find_path(trgt_x,trgt_y,diagonal=$game_system.pathfinding_diagonal, max_iterations=$game_system.pathfinding_iterations) path=$game_map.find_path(self.x,self.y,trgt_x,trgt_y,diagonal, max_iterations,self) @move_route.list.delete_at(@move_route_index) path.each { |i| @move_route.list.insert(@move_route_index,i) } @move_route_index-=1 end def force_path(trgt_x,trgt_y,diagonal=$game_system.pathfinding_diagonal, max_iterations=$game_system.pathfinding_iterations) path=$game_map.find_path(self.x,self.y,trgt_x,trgt_y,diagonal, max_iterations,self) path.reverse! path.push(RPG::MoveCommand.new(0)) move_route=RPG::MoveRoute.new move_route.list,move_route.repeat=path,false force_move_route(move_route) end end class Game_Map def removefrom_binaryheap @open_nodes[1],v=@open_nodes[@listsize],1 @listsize-=1 loop do w=2*(u=v) if w+1<=@listsize v=w if @total_cost[@open_nodes[u]]>=@total_cost[@open_nodes[w]] v=w+1 if @total_cost[@open_nodes[v]]>=@total_cost[@open_nodes[w+1]] elsif w<=@listsize v=w if @total_cost[@open_nodes[u]]>=@total_cost[@open_nodes[w]] end if u==v;break;else temp=@open_nodes[u] @open_nodes[u]=@open_nodes[v] @open_nodes[v]=temp end end end def find_path(src_x,src_y,trgt_x,trgt_y,diagonal,max_iterations,char) path=[] return path if !char.passable?(trgt_x,trgt_y) max_elements=width*height+2 openx=Table.new(max_elements) openy=Table.new(max_elements) @open_nodes=Table.new(max_elements) @total_cost=Table.new(max_elements) heuristic=Table.new(max_elements) step_cost=Table.new(width,height) parent_x=Table.new(width,height) parent_y=Table.new(width,height) actual_list=Table.new(width,height) new_openid,@open_nodes[1]=1,1 openx[1],openy[1]=src_x,src_y dist=[(trgt_x-src_x).abs,(trgt_y-src_y).abs] heuristic[1]=diagonal ? (dist.max*14)+(dist.min*10):(dist[0]+dist[1])*10 @total_cost[1]=heuristic[1] actual_list[src_x,src_y]=1 @listsize,count=1,0 loop do break if actual_list[trgt_x,trgt_y]!=0 count+=1 Graphics.update if count%500==0 return path if count==max_iterations return path if @listsize==0 node=@open_nodes[1] parent_xval,parent_yval=openx[node],openy[node] actual_list[parent_xval,parent_yval]=2 removefrom_binaryheap for i in 0...8 break if i>3&&!diagonal x,y=case i when 0 then [parent_xval,parent_yval-1] # UP when 1 then [parent_xval,parent_yval+1] # DOWN when 2 then [parent_xval-1,parent_yval] # LEFT when 3 then [parent_xval+1,parent_yval] # RIGHT when 4 then [parent_xval-1,parent_yval-1] # UP LEFT when 5 then [parent_xval+1,parent_yval-1] # UP RIGHT when 6 then [parent_xval-1,parent_yval+1] # DOWN LEFT when 7 then [parent_xval+1,parent_yval+1] # DOWN RIGHT end next if actual_list[x,y] == 2 next unless char.passable?(x,y) if i > 3 next unless case i when 4 then char.passable?(x+1,y)||char.passable?(x,y+1) when 5 then char.passable?(x-1,y)||char.passable?(x,y+1) when 6 then char.passable?(x+1,y)||char.passable?(x,y-1) when 7 then char.passable?(x-1,y)||char.passable?(x,y-1) end end plus_step_cost=((x-parent_xval).abs+(y-parent_yval).abs)>1 ? 14 : 10 temp_step_cost=step_cost[parent_xval,parent_yval]+plus_step_cost if actual_list[x,y]==1 if temp_step_cost<step_cost[x,y] parent_x[x,y]=parent_xval parent_y[x,y]=parent_yval step_cost[x,y]=temp_step_cost index=1 while index<@listsize;index+=1 break if openx[@open_nodes[index]]==x &&openy[@open_nodes[index]]==y end @total_cost[@open_nodes[index]]=temp_step_cost+heuristic[@open_nodes[index]] else next end else new_openid+=1;@listsize+=1 @open_nodes[@listsize]=new_openid step_cost[x,y]=temp_step_cost d=[(trgt_x-x).abs,(trgt_y-y).abs] heuristic[new_openid]=diagonal ? (d.max*14)+(d.min*10) : (d[0]+d[1])*10 @total_cost[new_openid]=temp_step_cost+heuristic[new_openid] parent_x[x,y],parent_y[x,y]=parent_xval,parent_yval openx[new_openid],openy[new_openid]=x,y index,actual_list[x,y]=@listsize,1 end while index!=1 temp_node=@open_nodes[index] if @total_cost[temp_node]<=@total_cost[@open_nodes[index / 2]] @open_nodes[index]=@open_nodes[index / 2] index/=2;@open_nodes[index]=temp_node else;break end end end end path_x,path_y=trgt_x,trgt_y while path_x!=src_x||path_y!=src_y prnt_x,prnt_y=parent_x[path_x,path_y],parent_y[path_x,path_y] if path_x<prnt_x;code=path_y<prnt_y ? 7 : path_y>prnt_y ? 5 : 2 elsif path_x>prnt_x ;code=path_y<prnt_y ? 8 : path_y>prnt_y ? 6 : 3 else ;code=path_y<prnt_y ? 4 : 1 end path.push(RPG::MoveCommand.new(code)) path_x,path_y=prnt_x,prnt_y end return path end end
Déplacement - Spoiler:
- Code:
-
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # Déplacement à la souris II Reloaded # par Berka 31/12/2009 rgss2 (VX) #-------------------------------------------------------------------------------------------------------------------------------------- # Ne pas publier sans autorisation expresse. http://www.rpgmakervx-fr.com #-------------------------------------------------------------------------------------------------------------------------------------- # Selection de personnages à la souris avec rectangle de sélection # Déplacement par clic droit # Scroll de la carte lorsque la souris est placée sur le bord de la fenetre # Déplacement du héro si rien n'est sélectionné #-------------------------------------------------------------------------------------------------------------------------------------- # Nécessite les scripts, normalement fournis avec ce script # - Clavier : crédits à TLN et Lordrik (script amélioré, support des touches de jeu par berka) # - Souris : crédits à Cybersam et Nearfantastica (ajout de la fonction drag&drop par berka) # - Pathfinding : crédits à Modern Algebra (tiré de l'algo A* expliqué par M.Lester) #-------------------------------------------------------------------------------------------------------------------------------------- # Tous les Réglages se font dans le présent script. # Bien mettre le commentaire "mobile" dans chaque événement déplacable. Sinon ca ne marche pas ! #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= module Berka module Selection T_Select = "clic gauche" # Touche de Sélection T_Bouge = "clic droit" # Touche de déplacement (cf. script Clavier) N_Curseur = "normal.png" # Image du Curseur, placée dans ./System (Icone par défaut) Comment = "mobile" # Commentaire à ajouter aux events déplacables C_Selbord = Color.new(0,255,0,180) # Couleur du bord du rectangle de selection C_Selfond = Color.new(0,255,0,80) # Couleur du fonds du rectangle de sélection TonSelect = Tone.new(0,255,0,20) # Couleur des events selectionnés MargeScroll = 16 # Bordure de l'écran réactif au scroll VitesseScroll = 7 # Vitesse du scroll de la carte end end include Berka::Selection $souris.shcurseur(N_Curseur,8,8) $deplevents||={} class Scene_Map<Scene_Base alias :select_start :start alias :select_update :update alias :select_terminate :terminate def start @select,@events=Sprite_Select.new,[] select_start end def update select_update return if !$souris if Input.trigger?(T_Bouge) x,y=$souris.grid[0],$souris.grid[1] return $game_player.force_path(x,y)if @events.empty? Thread.new{@events.each{|e|e.force_path(x,y) if e.is_a?(Game_Event)}} sleep(0.01) end if Input.press?(T_Select) clear @select.visible=true $souris.drag(T_Select,@select){@events=$deplevents.select{|e,c|@select.chk?(*c)}.flatten @events.each{|e|e.selection=true if e.is_a?(Game_Event)} @select.update} return end chk_scroll end def clear @events.each{|e|e.selection=false if e.is_a?(Game_Event)} @events.clear end def terminate @select.dispose select_terminate end def chk_scroll m=MargeScroll;x,y=$souris.update i=2 if x.between?(0,544-m)&&y.between?(416-m,416) i=4 if x.between?(0,m)&&y.between?(0,416-m) i=6 if x.between?(544-m,544)&&y.between?(m,416) i=8 if x.between?(m,544)&&y.between?(0,m) $game_map.start_scroll(i,1,VitesseScroll)if i end end class Sprite_Select<Sprite_Base attr_writer :width,:height,:rect def initialize super self.bitmap=Bitmap.new(544,416) @width,@height=0,0 end def update super self.bitmap.clear self.bitmap.fill_rect(0,0,@width,@height,C_Selbord) self.bitmap.fill_rect(1,1,@width-2,@height-2,C_Selfond) end def chk?(x,y) x-=$game_map.display_x/8;y-=$game_map.display_y/8 x.between?(self.x,self.x+@width)&&y.between?(self.y,self.y+@height) end end class Game_Character alias :select_cinit :initialize attr_accessor :tone def initialize @tone=Tone.new(0,0,0,0) select_cinit end end class Game_Event<Game_Character alias :select_init :initialize alias :select_upd :update attr_accessor :selection def initialize(*args) select_init(*args) @selection=false for i in 0...@list.size;@bouge=true if @list[i].parameters[0]==Comment;end end def update $deplevents[self]=[self.screen_x,self.screen_y]if @bouge @tone=(@selection ? TonSelect : Tone.new(0,0,0,0)) select_upd end end class Sprite_Character<Sprite_Base alias :select_upd :update def update self.tone=@character.tone select_upd end end
Voila, j'espère qu'il vous plaira. Bien sur, demandez moi avant de poster ce script à droit à gauche. Simple question de politesse. berka |
|