Zurück   Flashforum > Flash > ActionScript > ActionScript 1

Antwort
 
LinkBack Themen-Optionen Ansicht
Alt 08-11-2006, 18:20   #1 (permalink)
new user
 
Benutzerbild von PinkDragon
 
Registriert seit: Oct 2005
Beiträge: 140
Post Funktion beschleunigen?

Hi

Zuerst mal hoffe ich das richtige Forum erwischt zu haben, obwohl es um eine Funktion einer Klasse geht :P

Da mir die ständigen Kollisionsabfragen mit dem Standart hitTest noch den letzten Nerv rauben, dachte ich mir ich schreib einfach selber welche. Gesagt getan, es funktioniert auch schon mal einwandfrei jetzt aber die Frage: Geht das nicht auch schneller? Bzw. wie kann ich den Script noch optimieren, ohne die Grundidee zu verwerfen?
Würde mir echt helfen, wenn ich noch ein paar Tipps bekäme, da ich eine Reihe von solchen Kollisionsabfragen machen möchte und welche nicht zuuuuu langsam sein sollten...

Hier endlich der Code:
PHP-Code:
class HitTest{
  public function 
Circle_Rect(circle:MovieClip,
                              
rect:MovieClip){
    var 
xpos          circle._x;
    var 
ypos          circle._y;
    var 
radius        circle._width 2;
    var 
rect_width    rect._width;
    var 
rect_height   rect._height;
    var 
rect_x        rect._x;
    var 
rect_y        rect._y;

    if( 
Math.absxpos rect_x ) <= rect_width radius )
      if( 
Math.absypos rect_y ) <= rect_height radius )
        if( 
Math.absxpos rect_x ) <= rect_width || Math.absypos rect_y ) <= rect_height 2){
          var 
punkt = [0,0];
          if(
Math.absxpos rect_x ) <= rect_width )    punkt[1] = radius * ((rect_y ypos) ? : -1);
          if(
Math.absypos rect_y ) <= rect_height )    punkt[0] = radius * ((rect_x xpos) ? : -1);
          return(
punkt);
        }else{
          var 
xpos rect_x rect_width 2;
          var 
ypos rect_y rect_height 2;
          if( 
<= radius radius) return([-x,-y]);
          else{
            var 
xpos rect_x rect_width 2;
            var 
ypos rect_y rect_height 2;
            if( 
<= radius radius) return([-x,-y]);
            else{
              var 
xpos rect_x rect_width 2;
              var 
ypos rect_y rect_height 2;
              if( 
<= radius radius) return([-x,-y]);
              else{
                var 
xpos rect_x rect_width 2;
                var 
ypos rect_y rect_height 2;
                if( 
<= radius radius) return([-x,-y]);
                else return(
false);
              }
            }
          }
        }
      else return(
false);
    else return(
false);
  }

Es wird davon ausgegangen, dass "circle" ein Kreis ist und "rect" ein Rechteck, bei denen jeweils der Mittelpunkt in der Mitte ist (klingt seltsam aber was solls...) und die nicht gedreht sind. (Naja der Kreis darf ruhig gedreht sein )

mfg
PD
PinkDragon ist offline   Mit Zitat antworten
Alt 08-11-2006, 20:51   #2 (permalink)
Techniker
 
Benutzerbild von hgseib
 
Registriert seit: Sep 2003
Ort: 64807
Beiträge: 16.322
die aussenkanten bekommst du eleganter via getBounds(..

anderer lösungsansatz, weil nichts ist schneller als eingebaute funktionen:
http://www.seibsprogrammladen.de/fra...ispiele/flash6
-> DragImRaum (NoDrawArea)
__________________
die ultimative antwort auf alle programmierfragen: der debugger
mfg h.g.seib www.SeibsProgrammLaden.de

Geändert von hgseib (08-11-2006 um 21:53 Uhr)
hgseib ist offline   Mit Zitat antworten
Alt 09-11-2006, 09:58   #3 (permalink)
new user
 
Benutzerbild von PinkDragon
 
Registriert seit: Oct 2005
Beiträge: 140
Das Problem am anderen Lösungsansatz ist nur, dass kein Kollisionspunkt zurückgegeben wird. (Was für den Abprall benötigt wird)

Klar sind Systemfunktionen schneller, aber leider gibt es keine Abfrage Kreis/Rechteck. Und mehrere Punkt/Figur Abfragen sind sicher langsamer als diese eine Funktion.

"getBounds(.." kenn ich nicht, kommt der erst ab F8? (hab atm nur F5 zur Hand und dessen Hilfe ist etwas...) Wäre nett, wenn du den Befehl beschreiben könntest. (inpud-outpud)

mfg
PD
PinkDragon ist offline   Mit Zitat antworten
Alt 09-11-2006, 10:18   #4 (permalink)
Techniker
 
Benutzerbild von hgseib
 
Registriert seit: Sep 2003
Ort: 64807
Beiträge: 16.322
"..dass kein Kollisionspunkt zurückgegeben wird.."
naja, bei deiner routine ja auch nicht. man kann 8 richtungen daraus ermitteln (0,45,90,135, .. grad).
trifft der kreis auf eine aussenkante, das kann man auch einfacher ermitteln. trifft der kreis auf eine ecke, dann hilft deine routine auch nicht wirklich weiter.


zitat aus der doku: getBounds
Verfügbarkeit: ActionScript 1.0; Flash Player 5

Beispiel:
var bounds_obj:Object = square_mc.getBounds(this);
for (var i in bounds_obj) {
trace(i+" --> "+bounds_obj[i]);
}

Ausgabe z.b.:
yMax --> 110
yMin --> 10
xMax --> 110
xMin --> 10

-------------
var rB = rect.getBonds(_root);
rB.xMax ==> rect_x + rect_width / 2
__________________
die ultimative antwort auf alle programmierfragen: der debugger
mfg h.g.seib www.SeibsProgrammLaden.de

Geändert von hgseib (09-11-2006 um 10:22 Uhr)
hgseib ist offline   Mit Zitat antworten
Alt 09-11-2006, 16:15   #5 (permalink)
new user
 
Benutzerbild von PinkDragon
 
Registriert seit: Oct 2005
Beiträge: 140
Erstmal thx! Dass mit getBounds ist genau sowas, was ich gesucht habe

Aber dann muss ich meine Funktion auch mal verteidigen ^^ Sie gibt tatsächlich den kollisionspunkt zurück (vor allem bei Kollision mit den Ecken) aber dieser Punkt ist von der Kugel aus gesehen.
Zitat:
man kann 8 richtungen daraus ermitteln
versteh ich nicht, da man doch den genauen Punkt erhält... oder war ich etwas zu voreilig? Werde die Funktion heute am Abend nochmal testen.

mfg
PD

PS:
Zitat:
zitat aus der doku: getBounds
Verfügbarkeit: ActionScript 1.0; Flash Player 5
Ich sagte ja ich komm mit der F5 Hilfe nicht zurecht
PinkDragon ist offline   Mit Zitat antworten
Alt 09-11-2006, 19:48   #6 (permalink)
Techniker
 
Benutzerbild von hgseib
 
Registriert seit: Sep 2003
Ort: 64807
Beiträge: 16.322
mal gibst du false mal ein array zurück
(setzt mal ein punkt-mc immer auf die von dir zurückgegebene koordinate - relativ zum kreis) da siehst du dein ergebnis.

wenn der kreis mit z.b. 1/6 seiner höhe waagrecht auf eine ecke trifft. berechnest du da den punkt bei 60 grad? nö

wenn der kreis komplett über eine ecke des rechtecks steht, gibts du da einen punkt auf der kreislinie zurück? nö

wenn der kreis teilweisse in das rechteck eingedrungen ist, dann gibt es zwei schnittpunkte auf dem kreis. berechnest du? nö

fazit: du gibst irgendetwas zurück, was auch immer das sein mag. egal, hauptsache dir machts spass und du kommst mit deiner eigenen routine klar ;-)
__________________
die ultimative antwort auf alle programmierfragen: der debugger
mfg h.g.seib www.SeibsProgrammLaden.de
hgseib ist offline   Mit Zitat antworten
Alt 10-11-2006, 10:35   #7 (permalink)
new user
 
Benutzerbild von PinkDragon
 
Registriert seit: Oct 2005
Beiträge: 140
Auch wenn es hier nicht primär darum geht, aber hier sieht man wie es (für mich zumindest) funzt. (Daraus kann man dann den Abprallwinkel / Vektor berechnen)
(Hier die exe, falls man aus irgendeinem Grund keinen Flash8-Player hat)

Aber gibt es vllt noch solche Verbesserungsvorschläge (wie getBounds)? Ich werd einfach mal weitermachen und hoffen, dass vllt noch irgendwo Ideen/Tipps auftauchen. (Nicht scheuen, einfach posten)

mfg
PD
PinkDragon ist offline   Mit Zitat antworten
Alt 10-11-2006, 15:06   #8 (permalink)
Techniker
 
Benutzerbild von hgseib
 
Registriert seit: Sep 2003
Ort: 64807
Beiträge: 16.322
ok, du berechnest den winkel (an der ecke) ausserhalb deiner function, oder du hast das jetzt ergänzt. egal.
hier noch ein paar 'schönheitsoperationen'
Code:
function Circle_Rect(circle:MovieClip, rect:MovieClip) {
  var radius = circle._width/2;
  var rr = radius*radius;
  var punkt = [0, 0];
  var rB = rect.getBounds(_root);
  var rW2 = rect._width/2;
  var dx = Math.abs(circle._x-rect._x);
  if (dx<=rW2+radius) {
    var dy = Math.abs(circle._y-rect._y);
    var rH2 = rect._height/2;
    if (dy<=rH2+radius) {
      if (dx<=rW2 || dy<=rH2) {
        if (dx<=rW2) punkt[1] = rect._y>circle._y ? radius : -radius;
        if (dy<=rH2) punkt[0] = rect._x>circle._x ? radius : -radius;
      } else {
        var x = circle._x-rB.xMin;
        var y = circle._y-rB.yMin;
        if (x*x+y*y<=rr) return ([-x, -y]);
        var y = circle._y-rB.yMax;
        if (x*x+y*y<=rr) return ([-x, -y]);
        var x = circle._x-rB.xMax;
        if (x*x+y*y<=rr) return ([-x, -y]);
        var y = circle._y-rB.yMin;
        if (x*x+y*y<=rr) return ([-x, -y]);
  } } }
  return punkt;
}
//
kreis.onPress = startDrag;
kreis.onRelease = stopDrag;
rechteck.onPress = startDrag;
rechteck.onRelease = stopDrag;
_root.onEnterFrame = function() {
	var p = Circle_Rect(kreis, rechteck);
	hit._x = kreis._x+p[0];
	hit._y = kreis._y+p[1];
};
aber OK ist die funktion dennoch nicht. sie gibt zwar jetzt kein gemisch mehr zurück (mal ein boolwert und mal ein array). der sinn von dem ding ist aber nicht diesen punkt zu berechnen (das ist offensichtlich nur ein hilfsmittel) sondern ob der kreis das rechteck überdeckt und den abprallwinkel? dann sollte das aus der namensgebung der funktion auch ersichtlich sein und die funktion sollte auch nur genau das tun. also es sollte besser sowas zurückgeben:
return {im_rect:true, abprallwinkel:w};
__________________
die ultimative antwort auf alle programmierfragen: der debugger
mfg h.g.seib www.SeibsProgrammLaden.de

Geändert von hgseib (10-11-2006 um 15:32 Uhr)
hgseib ist offline   Mit Zitat antworten
Alt 10-11-2006, 16:32   #9 (permalink)
new user
 
Benutzerbild von PinkDragon
 
Registriert seit: Oct 2005
Beiträge: 140
Okok die Namensgebung gehört vllt n bischen geändert...
Aber ist es wirklich schlecht, dass die Funktion mal ne Boolean mal nen Array zurück gibt? Dann kann man leicht mit if abfragen ob überhaupt eine Kollision stattfindet und wenn ja gleich weiterrechnen.
Zitat:
var x = circle._x-rB.xMin;
var y = circle._y-rB.yMin;
if (x*x+y*y<=rr) return ([-x, -y]);
var y = circle._y-rB.yMax;
if (x*x+y*y<=rr) return ([-x, -y]);
var x = circle._x-rB.xMax;
if (x*x+y*y<=rr) return ([-x, -y]);
var y = circle._y-rB.yMin;
if (x*x+y*y<=rr) return ([-x, -y]);
Oh mir ist gar nicht aufgefallen, dass ich Variablen sinnlos doppelt setze... Aber soll ich die Else wirklich weglassen? Je früher die Funktion fertig ist desto besser, oder?

Zitat:
return {im_rect:true, abprallwinkel:w};
Den Abprallwinkel hab ich deshalb noch nicht in der Funktion übergeben, da ich noch irgendwie versuche alles mit Vektoren zu berechnen, was doch deutlich schneller sein sollte. Ausserdem müsste ich dann auch gleich die Eigengeschwindigkeit der Kugel mit übergeben und einbeziehen.
Hättest du vllt ne idee, wie ich ohne Winkelfunktionen den Abprall berechnen könnte, der Punkt der zusammen mit dem Mittelpunkt der Kugel das Lot für den Abprall bildet ist ja durch die Funktion schon mal gegeben.
PinkDragon ist offline   Mit Zitat antworten
Alt 10-11-2006, 16:56   #10 (permalink)
Techniker
 
Benutzerbild von hgseib
 
Registriert seit: Sep 2003
Ort: 64807
Beiträge: 16.322
"..Aber soll ich die Else wirklich weglassen?.."
return verlässt die funktion. was danach kommt interessiert nicht mehr.

"..wie ich ohne Winkelfunktionen den Abprall berechnen könnte.."
bei waagrecht und senkrecht ist das ja pillepalle.
bei den ecken kommts halt drauf an, wie realistisch du das machen willst. der kreis kann aus jedem beliebigen winkel in jeder beliebigen lage auf eine ecke treffen. hierzu einfallswinkel==ausfallswinkel zu berechnen wird ohne winkelfunktionen kaum gehen?

also vielleicht so?
return {type:0};
return {type:1, dx:y, dy:x};
return {type:2, abprallwinkel:w};
mit
type:0 ==> keine berührung
type:1 ==> treffer auf den geraden
type:2 ==> treffer auf der ecke
und
dx + dy ein wert von -1..1


ich weiss halt nicht was du machen willst (und wills auch garnicht wissen ;-)
wenn ich sowas mache dann entweder vereinfacht: es gibt nur waagrecht + senkrecht. ecken werden als zu aufwendig vernachlässigt.
oder wenn schon, dann richtig: das rechteck hat vier kanten und an den ecken je ein kreisbogen (radius 0 ist auch ein kreisbogen) und das ganze in jedem beliebigen drehwinkel.


dieses halb und halb mischding, das du versuchst, ist im ergebnis eben nur halb und halb ;-) es ist nicht besonders schnell, nicht übersichtlich/einfach und das ergebnis ist interpretationsbedürftig. der versuch war's wert, aber im ergebnis wäre das für mich keine lösung.
__________________
die ultimative antwort auf alle programmierfragen: der debugger
mfg h.g.seib www.SeibsProgrammLaden.de
hgseib ist offline   Mit Zitat antworten
Alt 16-11-2006, 17:48   #11 (permalink)
new user
 
Benutzerbild von PinkDragon
 
Registriert seit: Oct 2005
Beiträge: 140
Hab jetzt ein bischen weitergebastelt und imho kann sich das Ergebniss durchaus sehen lassen. Es Berechnet den Abprallvektor eines Kreises (Mit Eigengeschwindigkeit) bei einer Kollision mit einem gedrehten Rechteck und das (fast) ohne Winkelfunktionen und ohne Wurzeln. (Nur bei der Drehmatrix)
Hier kann das Ergebnis angesehen werden. Aber trotzdem kommt mir die Funktion unnötig kompliziert und lang vor oO. Daher kommt wieder mal die Frage, wie kann ich sie optimieren, ohne das Prinzip komplett zu ändern.
Hier ist das as File und hier das "Vorzeigebeispiel" als fla. (Für den Script brauch ich keine Tipps, der ist ***)

Hoffe irgendwer kennt sich bei meinen *übersichtlichen* Funktionen aus und kann mir helfen. *zuhgseibwink*

mfg
PD

Geändert von PinkDragon (16-11-2006 um 17:49 Uhr)
PinkDragon ist offline   Mit Zitat antworten
Antwort

Lesezeichen

Themen-Optionen
Ansicht

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks sind an
Pingbacks sind an
Refbacks sind an



Alle Zeitangaben in WEZ +1. Es ist jetzt 13:40 Uhr.

Domains, Webhosting & Vserver von Host Europe
Unterstützt das Flashforum!
Adobe User Group


Copyright ©1999 – 2012 Marc Thiele