ERLEDIGT
NEIN
NEIN
ANTWORTEN
4
4
ZUGRIFFE
634
634
EMPFEHLEN
-
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.
-
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ß
-
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
Außerdem gibt es noch ein paar Methoden die die Checkpunkte verwalten: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 != 0 || movementY != 0){
trace("movement", movementX, movementY);
//Nach Rechts
if(movementX > 0){
//Checkpoints nach Links versetzen und prüfen
xCollision = checkAt(-1, 0);
//Nach Links
} else if(movementX < 0) {
//Checkpoints nach Rechts versetzen
xCollision = checkAt(1, 0);
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(0, 1);
}
//Case 1: sonderfall
if(xCollision && yCollision){
trace("critical")
handleCollision(movementX, movementY);
}
//Case 2: only yCollision handled
else if(xCollision && !yCollision){
handleCollision(0, movementY);
}
//Case 3: only xCollision handled
else if(!xCollision && yCollision){
handleCollision(movementX, 0);
}
//Case 4: beide müssen
else if(!xCollision && !yCollision){
handleCollision(movementX, movementY);
}
}
}
/*
* Position checkpoints and character according to Parameters based on Collision detection
* @param x/yReposition (-1, 0, 1)
*/
public function handleCollision(xReposition:int, yReposition:int):void {
trace(xReposition, yReposition);
//Reposition x
if(xReposition < 0){
trace("left collision");
x = world.roundCrd(x, 0);
xAcceleration=0;
} else if(xReposition > 0){
trace("right collision");
x = world.roundCrd(x, 1)-width-1;
xAcceleration=0;
}
//Same for y
if(yReposition < 0){
trace("ceiling collision");
y = world.roundCrd(y, 0);
yAcceleration=0;
} else if(yReposition > 0){
trace("bottom collision");
y = world.roundCrd(y, 1)-height-1;
yAcceleration=0;
}
//Finally move the Checkpoints at Character Position
moveCheckpoints(x, y);
}
Die Checkpoint.as sieht so aus:PHP-Code:/*
* Factory Method to create the Checkpoints
* @param x/y Character position
* @param width/height Character dimensions
*/
public function newCheckpoints(x:int, y:int, width:int, height:int):void {
checkpoints[0] = new Checkpoint(x, y); //Oben links
checkpoints[1] = new Checkpoint(x + width, y); //Oben rechts
checkpoints[2] = new Checkpoint(x, y + height, true); //Unten links + checkBottom
checkpoints[3] = new Checkpoint(x + width, y + height, true); //Unten rechts + checkBottom
}
/*
* sdf
*/
public function checkAt(offsetX:int, offsetY:int):Boolean{
//Move all Checkpoints
if (checkpoints[0].checkAt(offsetX, offsetY)) return true;
if (checkpoints[1].checkAt(offsetX, offsetY)) return true;
if (checkpoints[2].checkAt(offsetX, offsetY)) return true;
if (checkpoints[3].checkAt(offsetX, offsetY)) 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:int, y:int):void{
//Move all Checkpoints
checkpoints[0].moveTo(x, y); //Oben links
checkpoints[1].moveTo(x + width, y); //Oben rechts
checkpoints[2].moveTo(x, y + height); //Unten links
checkpoints[3].moveTo(x + width, y + height); //Unten rechts
}
/*
* Checks for every checkpoint for x Collision
* @return Direction of Movement (-1,0,1)
*/
public function xAreColliding():int{
for (var i:int=0; i<4; i++) {
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=0; i<4; i++) {
if (checkpoints[i].yIsColliding()) return checkpoints[i].yIsColliding();
}
return 0;
}
Ich glaube, dass der Fehler beim Kollisionshandling und nicht bei der Abfrage liegt.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:int, y:int, checkBottom:Boolean = false){
//x+y Coordinates
this.x = x;
this.y = y;
//Use this Checkpoint to check for Bottom Material
this.checkBottom = checkBottom;
//X and Y Tile in Worldmap + bottomY (1px under Point)
this.X = x / World.tileWidth;
this.Y = y / World.tileHeight;
if(this.checkBottom) this.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:int, y:int):void{
//Calc Position in Tile-grid
tempX = x / World.tileWidth;
tempY = y / World.tileHeight;
bottomY = (y+1) / World.tileHeight;
//Set new Position
this.x = x;
this.y = y;
//Calculate Movement in tile-grid
xMovement = tempX - X;
yMovement = tempY - Y;
//Save new tile-grid Position
X = tempX;
Y = tempY;
//Get Material from new Position to check for constraints and Bottom
getMaterial();
}
public function checkAt(offsetX:int, offsetY:int):Boolean{
var gridX:int = (x / World.tileWidth) + offsetX;
var gridY:int = (y / 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.isBottom) onBottom = true;
else onBottom = false;
}
/* Checks if y-Movement is Colliding based on Movement and Material Constraints */
public function yIsColliding():int{
if (yMovement < 0 && currentMaterial.blockedBottom) return -1;
else if (yMovement > 0 && 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 < 0 && currentMaterial.blockedRight) return -1;
else if (xMovement > 0 && currentMaterial.blockedLeft) return 1;
else return 0;
}
}
}
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)
-
Marius - was genau verstehst du unter einem Checkpoint, und was machen die Variabel tempX, tempY, X, Y?
-
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
-
Einfache Node-Validierung gesucht
Von akins im Forum PHPAntworten: 1Letzter Beitrag: 19.04.08, 16:24 -
Einfache PHP Gallery gesucht
Von Gladiator6 im Forum PHPAntworten: 9Letzter Beitrag: 17.09.06, 13:37 -
Einfache DB-Suche gesucht!
Von Fleck06 im Forum PHPAntworten: 1Letzter Beitrag: 01.07.06, 04:11 -
Einfache Schnittmaske! Geht aber nicht
Von Fleck06 im Forum Vektor-ProgrammeAntworten: 4Letzter Beitrag: 13.06.06, 03:00 -
will ne einfache seite in php machen, aber wie fang ich an?
Von zg peripherals im Forum PHPAntworten: 20Letzter Beitrag: 12.01.02, 13:23





Zitieren

Login





