tutorials.de Buch-Aktion 05/2012
ERLEDIGT
NEIN
ANTWORTEN
4
ZUGRIFFE
634
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    Registriert seit
    Apr 2004
    Beiträge
    573
    Blog-Einträge
    1
    Hallo Leute,

    ich programmiere gerade an einem Jump and Run in Flash, die Kollisionsabfrage bereitet mir allerdings derzeit Probleme.
    Derzeit wird berechnet ob sich einer von den 4 Eckpunkten der Figur in ein anderes Teil bewegt, das Tile wird dann angefragt ob es aus dieser Richtung begehbar ist, wenn nein weiß ich, dass eine
    Kollision stattgefunden hat und muss den Character in die richtige Richtung an die Wand setzen. Bisher hat es nicht gescheit geklappt.
    Hat jemand eine 100%ig funktionierende Kollisionsabfrage für ein tile-based Spiel? Ohne Dinge wie hitTest und so natürlich, das braucht es ja nicht. Ob
    eine Kollision stattfindet kann man ja durch ne einfache Division durch die Teilchengröße bestimmen wenn man das Ergebnis in nem Integer speichert.
    Tutorials hab ich nichts dolles gefunden, tonypa ist nicht das was ich gesucht habe, es gibt noch eins für C, das finde ich aber auch seltsam.
     

  2. #2
    Avatar von Jens B.
    Jens B. Jens B. ist offline Damn good coffee!
    tutorials.de Premium-User
    Registriert seit
    Nov 2001
    Beiträge
    2.477
    Hey Marius,
    magst du uns deine bisherigen Versuche zeigen, vllt finden wir ja heraus was falsch läuft. Vor allem die "einfache Division" würde mich mal interessieren, denn ganz so einfach stelle ich mir die nicht vor.

    Vllt hilft dir ja das hier etwas
    http://www.tutorials.de/forum/flash-...extfelder.html

    Gruß
     

  3. #3
    Registriert seit
    Apr 2004
    Beiträge
    573
    Blog-Einträge
    1
    Hi,

    ich kann mal den betreffenden Teil posten, das ganze ist AS3 und auf mehrere Klassen aufgeteilt.

    In der Character.as werden jedes Frame die Physikberechnung und danach die Kollisionsberechnung aufgerufen
    PHP-Code:
    public function ckeckCollision():void{
                
    //Recalculate Material under new Position
                
    calculateMaterial();
                
    //Check if x moved into a Material which is blocked in this direction (same for Y-direction)
                
    movementX xAreColliding();
                
    movementY yAreColliding();
                var 
    xCollision:Boolean;
                var 
    yCollision:Boolean;
                
                
    //Collision has to be checked, cause the character has moved into another Tile
                
    if(movementX != || movementY != 0){
                    
    trace("movement"movementXmovementY);
                    
                    
    //Nach Rechts
                    
    if(movementX 0){
                        
    //Checkpoints nach Links versetzen und prüfen
                        
    xCollision checkAt(-10);
                    
    //Nach Links
                    
    } else if(movementX 0) {
                        
    //Checkpoints nach Rechts versetzen
                        
    xCollision checkAt(10);
                        
    trace("xColl"xCollision);
                    }
                    
    //Nach Unten
                    
    if(movementY 0){
                        
    //Checkpoints nach Oben versetzen
                        
    yCollision checkAt(0, -1);
                        
    trace("yColl"yCollision);
                    
    //Nach Oben
                    
    } else if(movementY 0) {
                        
    //Checkpoints nach Unten versetzen
                        
    yCollision checkAt(01);
                    }
                    
                    
    //Case 1: sonderfall
                    
    if(xCollision && yCollision){
                        
    trace("critical")
                        
    handleCollision(movementXmovementY);
                    }
                    
    //Case 2: only yCollision handled
                    
    else if(xCollision && !yCollision){
                        
    handleCollision(0movementY);
                    }
                    
    //Case 3: only xCollision handled
                    
    else if(!xCollision && yCollision){
                        
    handleCollision(movementX0);
                    }
                    
    //Case 4: beide müssen
                    
    else if(!xCollision && !yCollision){
                        
    handleCollision(movementXmovementY);
                    }
                }
            }
            
    /*
             * Position checkpoints and character according to Parameters based on Collision detection
             * @param x/yReposition (-1, 0, 1)
             */
            
    public function handleCollision(xReposition:intyReposition:int):void {
                
    trace(xRepositionyReposition);
                
    //Reposition x
                
    if(xReposition 0){
                    
    trace("left collision");
                    
    world.roundCrd(x0);
                    
    xAcceleration=0;
                } else if(
    xReposition 0){
                    
    trace("right collision");
                    
    world.roundCrd(x1)-width-1;
                    
    xAcceleration=0;
                }
                
    //Same for y
                
    if(yReposition 0){
                    
    trace("ceiling collision");
                    
    world.roundCrd(y0);
                    
    yAcceleration=0;
                } else if(
    yReposition 0){
                    
    trace("bottom collision");
                    
    world.roundCrd(y1)-height-1;
                    
    yAcceleration=0;
                }
                
    //Finally move the Checkpoints at Character Position
                
    moveCheckpoints(xy);
            } 
    Außerdem gibt es noch ein paar Methoden die die Checkpunkte verwalten:
    PHP-Code:
    /*
             * Factory Method to create the Checkpoints
             * @param x/y Character position
             * @param width/height Character dimensions
             */
            
    public function newCheckpoints(x:inty:intwidth:intheight:int):void {
                
    checkpoints[0] = new Checkpoint(xy);                    //Oben links
                
    checkpoints[1] = new Checkpoint(widthy);            //Oben rechts
                
    checkpoints[2] = new Checkpoint(xheighttrue);            //Unten links + checkBottom
                
    checkpoints[3] = new Checkpoint(widthheighttrue);    //Unten rechts + checkBottom
            
    }
            
    /*
             * sdf
             */
            
    public function checkAt(offsetX:intoffsetY:int):Boolean{
                
    //Move all Checkpoints
                
    if (checkpoints[0].checkAt(offsetXoffsetY)) return true;
                if (
    checkpoints[1].checkAt(offsetXoffsetY)) return true;
                if (
    checkpoints[2].checkAt(offsetXoffsetY)) return true;
                if (
    checkpoints[3].checkAt(offsetXoffsetY)) return true;
                
                return 
    false;
            }
            
    /*
             * Moves all Checkpoints to a specified position
             * @param x/y top-left Character x/y-Coordinate
             * @param asTileCoord are x and y full Coordinates or divided by TileWidth/Height
             * @param temporary Only temporary Movement for checking
             */
            
    public function moveCheckpoints(x:inty:int):void{
                
    //Move all Checkpoints
                
    checkpoints[0].moveTo(xy);                    //Oben links
                
    checkpoints[1].moveTo(widthy);            //Oben rechts
                
    checkpoints[2].moveTo(xheight);            //Unten links
                
    checkpoints[3].moveTo(widthheight);    //Unten rechts
            
    }
    /*
             * Checks for every checkpoint for x Collision
             * @return Direction of Movement (-1,0,1)
             */
            
    public function xAreColliding():int{
                for (var 
    i:int=0i<4i++) {
                    if (
    checkpoints[i].xIsColliding()) return checkpoints[i].xIsColliding();
                }
                return 
    0;
            }
            
    /*
             * Checks for every checkpoint for y Collision
             * @return Direction of Movement (-1,0,1)
             */
            
    public function yAreColliding():int{
                for (var 
    i:int=0i<4i++) {
                    if (
    checkpoints[i].yIsColliding()) return checkpoints[i].yIsColliding();
                }
                return 
    0;
            } 
    Die Checkpoint.as sieht so aus:
    PHP-Code:
    package de.mariusheil.jump.world {

        
    /**
         * @author Marius Heil
         */
        
    public class Checkpoint {
            public var 
    checkBottom:Boolean;
            public var 
    x:Number;
            public var 
    y:Number;
            public var 
    xBackup:Number;
            public var 
    yBackup:Number;
            public var 
    X:int;
            public var 
    Y:int;
            public var 
    bottomY:int;
            public var 
    tempX:int;
            public var 
    tempY:int;
            public var 
    xMovement:int;
            public var 
    yMovement:int;
            public var 
    currentMaterial:Material;
            public var 
    onBottom:Boolean;
            
            
    /*
             * Creates a Checkpoint at specific Coordinates
             * @param x/y The initial Coordinates
             * @param checkBottom if set to true this Checkpoint will look for bottom 1 pixel below
             */
            
    public function Checkpoint(x:inty:intcheckBottom:Boolean false){
                
    //x+y Coordinates
                
    this.x;
                
    this.y;
                
    //Use this Checkpoint to check for Bottom Material
                
    this.checkBottom checkBottom;
                
    //X and Y Tile in Worldmap + bottomY (1px under Point)
                
    this.World.tileWidth;
                
    this.World.tileHeight;
                if(
    this.checkBottomthis.bottomY = (y+1) / World.tileHeight;
                
    //Movement in Tiles (-1; 0; 1)
                
    this.xMovement 0;
                
    this.yMovement 0;
                
    getMaterial();
            }
            
    /*
             * Moves the Checkpoint to a specific Coordinate
             * @param x/y new Position
             * @param temporary Set to true if you just want to calculate how the Movement would be
             */
            
    public function moveTo(x:inty:int):void{
                
    //Calc Position in Tile-grid
                
    tempX World.tileWidth;
                
    tempY World.tileHeight;
                
    bottomY = (y+1) / World.tileHeight;
                
    //Set new Position
                
    this.x;
                
    this.y;
                
    //Calculate Movement in tile-grid
                
    xMovement tempX X;
                
    yMovement tempY Y;
                
    //Save new tile-grid Position
                
    tempX;
                
    tempY;
                
    //Get Material from new Position to check for constraints and Bottom
                
    getMaterial();
            }
            public function 
    checkAt(offsetX:intoffsetY:int):Boolean{
                var 
    gridX:int = (World.tileWidth) + offsetX;
                var 
    gridY:int = (World.tileHeight) + offsetY;
                
                if(
    xMovement 0){
                    if(
    World.tileMap[gridX][gridY].material.blockedRight) return true;
                } else if(
    xMovement 0){
                    if(
    World.tileMap[gridX][gridY].material.blockedLeft) return true;
                }
                if(
    yMovement 0){
                    if(
    World.tileMap[gridX][gridY].material.blockedBottom) return true;
                } else if(
    yMovement 0){
                    if(
    World.tileMap[gridX][gridY].material.blockedTop) return true;
                }            
                
                return 
    false;
            }
            
            
    /* Fetches Material at Checkpoint Position */
            
    public function getMaterial():void {
                
    //Save Reference to tileMaterial
                
    currentMaterial World.tileMap[X][Y].material;
                
    //Boden prüfen
                
    if(checkBottom && World.tileMap[X][bottomY].material.isBottomonBottom true;
                    else 
    onBottom false;
            }
            
    /* Checks if y-Movement is Colliding based on Movement and Material Constraints */
            
    public function yIsColliding():int{
                if (
    yMovement && currentMaterial.blockedBottom) return -1;
                else if (
    yMovement && currentMaterial.blockedTop) return 1;
                else return 
    0;
            }
            
    /* Checks if x-Movement is Colliding based on Movement and Material Constraints */
            
    public function xIsColliding():int{
                if (
    xMovement && currentMaterial.blockedRight) return -1;
                else if (
    xMovement && currentMaterial.blockedLeft) return 1;
                else return 
    0;
            }
        }

    Ich glaube, dass der Fehler beim Kollisionshandling und nicht bei der Abfrage liegt.
    Bei der Kollisionsabfrage mache ich zB sowas:
    var gridX:int = (x / World.tileWidth) + offsetX;
    x / tileWidht gibt mir da es in einem Integer gespeichert wird den Index vom tileArray an den ich dann nur noch nach dem Material fragen muss.
    offsetX ist in dem Fall zB -1, 0 oder 1, damit ich schauen kann ob der Character ein Feld weiter immer noch kollidieren würde.

    Das Tutorial schau ich grad mal durch, weiß allerdings nciht ob es mir weiterhilft.

    ----
    Habs mir angeschaut, das hilft mir allerdings nicht groß, in meinem Fall liegt das Problem wohl eher beim Handling als bei der Abfrage selbst.
    Geändert von Marius Heil (08.05.10 um 14:33 Uhr)
     

  4. #4
    Avatar von Jens B.
    Jens B. Jens B. ist offline Damn good coffee!
    tutorials.de Premium-User
    Registriert seit
    Nov 2001
    Beiträge
    2.477
    Marius - was genau verstehst du unter einem Checkpoint, und was machen die Variabel tempX, tempY, X, Y?
     

  5. #5
    Registriert seit
    Apr 2004
    Beiträge
    573
    Blog-Einträge
    1
    Ein Checkpoint ist ne Instanz der Klasse Checkpoint, man weist einem Checkpoint einen x und y Wert zu und hat dann die Möglichkeit diese überprüfen zu lassen ob er in ein anderes Tile gewechselt ist. AUßerdem kann man sagen dass er auf Bodenkollision überprüfen soll, das geschieht einen Pixel unter dem wirklichen Checkpoint. Im wesentlichen ist es ein Punkt den man verschieben kann und den ich für Kollisionsabfragen benutze.
    Wenn X oder Y großgeschrieben sind, handelt es sich um die Koordinaten im Tileraster. Wenn zB x = 65 und die Teilchengröße 30 ist, dann ist X = 3.
    die temp-Variablen sind eigentlich unnötig, die werden nur für die Berechnung gebraucht, sind noch Überbleibsel aus vorherigen versuchen, die werd ich rauswerfen.
     

Ähnliche Themen

  1. Einfache Node-Validierung gesucht
    Von akins im Forum PHP
    Antworten: 1
    Letzter Beitrag: 19.04.08, 16:24
  2. Einfache PHP Gallery gesucht
    Von Gladiator6 im Forum PHP
    Antworten: 9
    Letzter Beitrag: 17.09.06, 13:37
  3. Einfache DB-Suche gesucht!
    Von Fleck06 im Forum PHP
    Antworten: 1
    Letzter Beitrag: 01.07.06, 04:11
  4. Einfache Schnittmaske! Geht aber nicht
    Von Fleck06 im Forum Vektor-Programme
    Antworten: 4
    Letzter Beitrag: 13.06.06, 03:00
  5. Antworten: 20
    Letzter Beitrag: 12.01.02, 13:23