JavascriptProva

venerdì 22 febbraio 2013

Rilevamento della sovrapposizione dell'oggetto alla proiezione orizzontale dell'ostacolo

Rilevamento della sovrapposizione dell'oggetto alla proiezione orizzontale dell'ostacolo:
function OnMouseMove(){
 
 Sx=BaseX+event.clientX-MouseX;
 Hi=BaseY+event.clientY-MouseY;
 Dx=Sx+EN(oggetto.currentStyle.width);
 Lo=Hi+EN(oggetto.currentStyle.height);
 if(HorProject(ostacolo)) {
  $("test").innerHTML= "centrato";
 }else{
  $("test").innerHTML="";
 }
 oggetto.style.left=Sx+"px";
 oggetto.style.top=Hi+"px";
}
usando la funzione che rileva la sovrapposizione dell'oggetto alla proiezione orizzontale dell'ostacolo:
function HorProject(ost){
 if(Hi<(EN(ost.currentStyle.top)+EN(ost.currentStyle.height)) && (Lo>EN(ost.currentStyle.top))) return true;
}
..la qual cosa andrebbe abbreviata...

Correzione coordinate dell'oggetto.

Correzione per le funzioni che ottengono le coordinate dell'oggetto.
Esse vengono calcolate direttamente nell'ambito della funzione OnMouseMove.
function OnMouseMove(){
 
 Sx=BaseX+event.clientX-MouseX;
 Hi=BaseY+event.clientY-MouseY;
 Dx=Sx+EN(oggetto.currentStyle.width);
 Lo=Hi+EN(oggetto.currentStyle.height);
 $("test").innerHTML= Hi+" "+Lo;
 oggetto.style.left=Sx+"px";
 oggetto.style.top=Hi+"px";
}
La verifica con la casella test (in blu) è positiva.

Una nuova idea per le collisioni: pensare la posizione dell'oggetto prima di attuarla...

Dunque... proviamo con un altro approccio.
Il codice può prima pensare alla posizione dell'oggetto e poi attuarla, in modo da eliminare posizioni reali e posizioni virtuali dovute a repentini rapidissimi spostamenti dell'oggetto.

Ecco: la funzione OnMouseMove che gestisce l'evento document.onmousemove mi dà valore alle variabili Sx e Hi, che sono le coordinate dell'angolo superiore sinistro dell'oggetto, ossia i lati sinistro e superiore del quadrato che costituisce l'oggetto.
Il codice, ovviamente, non muove minimamente l'oggetto.

Ora definiamo anche le coordinate degli altri lati, chiamiamole Dx e Lo.
var Sx,Hi,Dx,Lo;
E creiamo delle funzioni che le calcolino in relazione alla larghezza e all'altezza dell'oggetto.
function Dx(){
 return (Sx+oggetto.width);
}
function Lo(){
 return (Hi+oggetto.height);
}
Ecco.

La funzione OnMouseMove adesso ha questo aspetto:
function OnMouseMove(){
 
 Sx=BaseX+event.clientX-MouseX;
 Hi=BaseY+event.clientY-MouseY;
}
Proviamo a muovere l'oggetto...

che ovviamente non si muove.
Adesso concretizziamo le misure prese:
function OnMouseMove(){
 
 Sx=BaseX+event.clientX-MouseX;
 Hi=BaseY+event.clientY-MouseY;
 oggetto.style.left=Sx+"px";
 oggetto.style.top=Hi+"px";
}

e l'oggetto, come per incanto, si muove.

Ecco, adesso forse sarà più facile...

mercoledì 20 febbraio 2013

Analizziamo pazientemente (questo è il più grosso problema di programmazione con cui mi sia mai scontrato)

E' estremamente arduo.

Riproviamo dall'inizio.
Io faccio così: più mi incorno su un problema più mi ci impiccio, e più non ci cavo un ragno dal buco.
Ricominciamo.
Dato che il difetto fondamentale del resettare la posizione dell'oggetto nel momento in cui viene mosso è che la posizione dell'oggetto non corrisponde a quella che si vede, devo fermare l'oggetto nella posizione reale e non in una posizione virtuale.

Per fare questo, devo arrestare il movimento bloccando l'oggetto contro una linea, ma bloccandolo davvero.
La dinamica dei fatti è che quando viene mosso l'oggetto, esso viene mosso oltre l'ostacolo, e resettato poi a monte dell'ostacolo in un secondo tempo. La cosa potrebbe anche andare bene...

Ma proviamo ad arrestare il movimento realmente, in modo che l'oggetto non si possa più muovere orizzontalmente contro un ostacolo, ma solo nelle altre direzioni.
La funzione da modificare è questa:
function OnMouseMove(){
 oggetto.style.left=BaseX+event.clientX-MouseX;
 oggetto.style.top=BaseY+event.clientY-MouseY;
}
Modifichiamola un po'...
function OnMouseMove(){
 if(destro(oggetto)<500) oggetto.style.left=BaseX+event.clientX-MouseX;
 oggetto.style.top=BaseY+event.clientY-MouseY;
}
Bene. Mi sono creato una linea verticale che abbia per ascissa 500 per verificare dove si arresta il movimento.
Così facendo, se sposto l'oggetto lentamente, esso si arresta esattamente con il suo lato destro contro la linea verticale, ossia a 500 di ascissa, ma se vado velocemente, si arresta più a destra, perchè la posizione non viene espressa punto per punto.
Devo quindi correggere la posizione dell'oggetto.
function OnMouseMove(){

 if(destro(oggetto)<500) {
  oggetto.style.left=BaseX+event.clientX-MouseX;
 }else{
  oggetto.style.left=(500-larghezza(oggetto))+"px";
 }
 
 oggetto.style.top=BaseY+event.clientY-MouseY;
}
Sì, così funziona: anche andando a velocità supersonica, l'oggetto si arresta sempre a 500.
La differenza con il codice che usavo precedentemente è che prima l'oggetto veniva spostato oltre l'ostacolo e poi tornava dietro.
Lo riprovo:
function OnMouseMove(){

 oggetto.style.left=BaseX+event.clientX-MouseX;
 
 if(destro(oggetto)>500) oggetto.style.left=(500-larghezza(oggetto))+"px";

 oggetto.style.top=BaseY+event.clientY-MouseY;
}
Ecco: così facendo, prima l'oggetto viene spostato oltre l'ostacolo, quindi viene riportato indietro se il suo margine destro supera 500.
Questo accade a ogni movimento dell'oggetto. Non si vede, ma in realtà quando l'oggetto viene spinto contro l'ostacolo, per un infinitesimo va effettivamente oltre l'ostacolo e quindi, verificandosi la condizione "oltre l'ostacolo", viene rispinto indietro.

Nel primo caso, invece:
function OnMouseMove(){

 if(destro(oggetto)<500) {
  oggetto.style.left=BaseX+event.clientX-MouseX;
 }else{
  oggetto.style.left=(500-larghezza(oggetto))+"px";
 }
 
 oggetto.style.top=BaseY+event.clientY-MouseY;
}
l'oggetto viene mosso se il margine destro è minore del limite, altrimenti viene fissato contro il limite stesso
In questo secondo caso, non vi è una posizione "inapparente" dell'oggetto durante le primissime fasi del movimento, perchè esso viene arrestato subito nella sua posizione contro l'ostacolo.

venerdì 15 febbraio 2013

Pensieri sulle collisioni

Non funziona... Perchè?
Dunque, partiamo da zero...
L'oggetto scivola contro l'ostacolo in virtù del fatto che viene continuamente riportato, dalla sua posizione reale, ossia quella "attaccata" al cursore del mouse, nella posizione virtuale, ossia quella "aderente alla superficie dell'ostacolo". Il processo si svolge ogni volta che il cursore viene mosso, perchè questa funzione
function OnMouseMove(){
 prevSx=sinistro(oggetto);
 prevDx=destro(oggetto);
 prevHi=alto(oggetto);
 prevLo=basso(oggetto);
 oggetto.style.left=BaseX+event.clientX-MouseX;
 oggetto.style.top=BaseY+event.clientY-MouseY;

 verificaDirezione(sinistro(oggetto),destro(oggetto),alto(oggetto),basso(oggetto),ostacolo);
}
che intercetta l'evento "movimento del mouse", chiamando la funzione "verificaDirezione", dà all'oggetto delle coordinate corrispondenti alla posizione "strisciante sulla superficie dell'oggetto". A ogni movimento del mouse, in realtà, l'oggetto torna "attaccato al puntatore", per poi essere riportato "strisciante sull'oggetto".
La cosa non si nota perchè è molto rapida.
Così, se incontro un altro ostacolo attaccato al primo, e ripeto la funzione con il secondo ostacolo, ponendo come parametri della funzione le coordinate dell'oggetto, in realtà fornisco le coordinate "reali", ossia dell'oggetto che, per una frazione invisibile di secondo, si trova attaccato al cursore del mouse, non le coordinate "virtuali", ossia dell'oggetto che strofina contro il bordo dell'ostacolo.

giovedì 14 febbraio 2013

Blocco dell'oggetto contro l'ostacolo

Blocchiamo l'oggetto, adesso...
function verificaDirezione(oggSx,oggDx,oggHi,oggLo,ost){
  if(horOverDx(oggHi,oggLo,oggDx,ost)&& prevDx<=sinistro(ost)) {
   $("test").innerHTML="Da sinistra";
   oggSx=sinistro(ost)-larghezza(oggetto);
   oggDx=sinistro(ost);
   oggetto.style.left=oggSx+"px";
  }
  if(horOverSx(oggHi,oggLo,oggSx,ost)&& prevSx>=destro(ost)) {
   $("test").innerHTML="Da destra";
   oggSx=destro(ost)
   oggDx=destro(ost)+larghezza(oggetto);
   oggetto.style.left=oggSx+"px";
  }
   
  if(vertOverHi(oggSx,oggDx,oggLo,ost) && prevLo<=alto(ost)) {
   $("test").innerHTML="Da alto";
   oggHi=alto(ost)-altezza(oggetto);
   oggLo=alto(ost)
   oggetto.style.top=oggHi;
  }
  if(vertOverLo(oggSx,oggDx,oggHi,ost) && prevHi>=basso(ost)) {
   $("test").innerHTML="Da basso";
   oggHi=basso(ost);
   oggLo=basso(ost)+altezza(oggetto);
   oggetto.style.top=basso(ost);
  }
}
Ecco, così l'oggetto si blocca quando viene a cozzare con l'ostacolo.
La differenza rispetto al codice precedente è che il valore delle coordinate dell'oggetto bloccatosi viene immagazzinato in variabili a parte.
Le variabili vengono rigenerate all'inizio della funzione OnMouseMove.

domenica 10 febbraio 2013

Sintesi delle funzioni che rilevano la direzione di sovrapposizione di un oggetto a un ostacolo

Ora blocchiamo l'oggetto.

Prima fondiamo le funzioni, in modo da isolare il lavoro sporco...

Ecco il codice che verifica la direzione usando le funzioni predette:
if(horOverDx(alto(oggetto),basso(oggetto),destro(oggetto),ostacolo)&& prevDx<=sinistro(ostacolo)) $("test").innerHTML="Da sinistra";
 if(horOverSx(alto(oggetto),basso(oggetto),sinistro(oggetto),ostacolo)&& prevSx>=destro(ostacolo)) $("test").innerHTML="Da destra";
 if(vertOverHi(sinistro(oggetto),destro(oggetto),basso(oggetto),ostacolo) && prevLo<=alto(ostacolo)) $("test").innerHTML="Da alto";
 if(vertOverLo(sinistro(oggetto),destro(oggetto),alto(oggetto),ostacolo) && prevHi>=basso(ostacolo)) $("test").innerHTML="Da basso";
Come unificarlo?

Creo un'unica funzione verifica:
function verificaDirezione(oggSx,oggDx,oggHi,oggLo,ost){
 if(horOverDx(oggHi,oggLo,oggDx,ost)&& prevDx<=sinistro(ost)) $("test").innerHTML="Da sinistra";
 if(horOverSx(oggHi,oggLo,oggSx,ost)&& prevSx>=destro(ost)) $("test").innerHTML="Da destra";
 if(vertOverHi(oggSx,oggDx,oggLo,ost) && prevLo<=alto(ost)) $("test").innerHTML="Da alto";
 if(vertOverLo(oggSx,oggDx,oggHi,ost) && prevHi>=basso(ost)) $("test").innerHTML="Da basso";
}
Eccola, e viene richiamata così:
function OnMouseMove(){
 prevSx=sinistro(oggetto);
 prevDx=destro(oggetto);
 prevHi=alto(oggetto);
 prevLo=basso(oggetto);
 oggetto.style.left=BaseX+event.clientX-MouseX;
 oggetto.style.top=BaseY+event.clientY-MouseY;

 verificaDirezione(sinistro(oggetto),destro(oggetto),alto(oggetto),basso(oggetto),ostacolo);
}
Funziona!