Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- g.Collisions =
- {
- toTile: function(input,downOnBorder)
- {
- if( downOnBorder == null ) { downOnBorder = false; }
- var ret = Math.floor(input);
- if( downOnBorder && ( input % 1 ) === 0 )
- {
- ret--;
- }
- return ret;
- },
- getTiles: function(x,y,w,h,layers)
- {
- var ret = [];
- for( var sY = 0; sY < h; sY++ )
- {
- for( var sX = 0; sX < w; sX++ )
- {
- layers.forEach(function(layer)
- {
- ret.push(layer.layer.data[ y + sY ][ x + sX ]);
- });
- }
- }
- return ret;
- },
- /* isWall checks if a specified x/y tile is a wall
- additionally it can check if a NPC also has its bounding box inside that tiles
- @ x (integer) : x position to check (in tile coordinates)
- @ y (integer) : y position to check (in tile coordinates)
- @ layers (Phaser.Group/Array of Phaser.TilemapLayer) : the layers of the map to check
- @ checkNPC (boolean) : if the function should check for NPC bounding boxes intersecting with the tile
- returns: object info
- { collision, tileCollision, npcCollision }
- @ collision (boolean) : if a collision has been found
- @ tileCollision (array) : array of objects with info on the collision { layer, tile, collision } => layer is the layer of the collision, tile is the tile, collision is a boolean that says if it collided
- @ npcCollision (array) : array of NPC objects that collided (if checkNPC was true)
- */
- isWall: function(x, y, layers, checkNPC)
- {
- var tileCollisions = [];
- var collision = false;
- var layer;
- for( var i = 0, l = layers.length; i < l; i++ )
- {
- if( layers.type === Phaser.GROUP )
- {
- layer = layers.getAt(i);
- }
- else
- {
- layer = layers[i];
- }
- tileCollisions.push( { layer: layer, tile: layer.layer.data[y][x], collision: layer.layer.data[y][x].collides } );
- if( layer.layer.data[y][x].collides )
- {
- collision = true;
- }
- }
- return { collision: collision, tileCollision: tileCollisions, npcCollision: [] };
- },
- /* isAreaWall checks if a specified area has any collisions
- this will call isWall and always pass checkNPC as false, since it easier to just run its own check on the whole area it is checking
- @ x (integer) : x position to start the check (in tile coordinates)
- @ y (integer) : y position to start the check (in tile coordinates)
- @ w (integer) : width of the area to check (in tile coordinates)
- @ h (integer) : height of the area to check (in tile coordinates)
- @ layers (Phaser.Group/Array of Phaser.TilemapLayer) : the layers of the map to check
- @ checkNPC (boolean) : if the function should check for NPC bounding boxes intersecting with the area
- returns: object info
- { collision, tileCollision, npccollision }
- @ collision (boolean) : if any collision has been found
- @ tileCollided (boolean) : if a tile collided
- @ npcCollided (boolean) : if a npc collided
- @ tileCollision (2D-array) : 2D array of the checked area, each element being a return of isWall call
- @ npcCollision (array) : array of NPCs that have a bounding box that intersects or overlaps with the checked area
- */
- isAreaWall: function(x,y,w,h,layers,checkNPC)
- {
- var tileCollisions = [];
- var tileCollision = false;
- var collision = false;
- var npcCollision = false;
- for( var sX = 0; sX < w; sX++ )
- {
- tileCollisions[sX] = [];
- for( var sY = 0; sY < h; sY++ )
- {
- tileCollisions[sX][sY] = this.isWall( x + sX, y + sY, layers, false );
- if(tileCollisions[sX][sY].collision)
- {
- collision = true;
- tileCollision = true;
- }
- }
- }
- return { collision: collision, tileCollided: tileCollision, npcCollided: npcCollision, tileCollision: tileCollisions, npcCollision: [] };
- },
- /* isRectWall checks a rect with direction
- @ x (float) : x position of where the rect start (in world coordinates)
- @ y (float) : y position of where the rect starts (in world coordinates)
- @ w (float) : width of the rect
- @ h (float) : height of the rect
- @ direction (integer) : direction to stop through the rect (0 = up, 1 = right, 2 = down, 3 = left)
- @ layers (Phaser.Group/Array of Phaser.TilemapLayer) : the layers of the map to check
- @ checkNPC (boolean) : if the function should check for NPC bounding boxes intersecting with the rect
- @ stopOnFirst (boolean) : if to return on first step that has a collision or keep going
- returns object info
- { steps, collision, collisions }
- @ steps (integer) : steps taken
- @ collision (boolean) : if a collision happened at all
- @ collisions (array) : array, step as index, each value being a return of isAreaWall (thus [0] will always be the first step and so on
- */
- isRectWall: function(x,y,w,h,direction,layers,checkNPC,stopOnFirst)
- {
- var start;
- var end;
- var mod;
- var pos = [ x, y ];
- var tilePos = [ this.toTile(x), this.toTile(y) ];
- var size = [ w, h ];
- var tileSize = [ Math.ceil(w) + ( ((x % 0) !== 0) && ((w % 0) === 0) ? 1 : 0 ),
- Math.ceil(h) + ( ((y % 0) !== 0) && ((h % 0) === 0) ? 1 : 0 ) ];
- if(direction === 3 || direction === 0)
- {
- mod = -1;
- }
- else
- {
- mod = 1;
- }
- var stepIndex = (direction === 1 || direction === 3) ? 0 : 1;
- start = pos[stepIndex] + (mod === -1 ? size[stepIndex] : 0 );
- end = start + size[stepIndex] * mod;
- var startTile, endTile;
- startTile = this.toTile( start, mod === 1 );
- endTile = this.toTile( end, mod === 1 );
- var steps = Math.abs(startTile - endTile);
- var checkPos, checkSize;
- if(startTile === endTile)
- {
- return { steps: 0, collision: false, collisions: [] };
- }
- else
- {
- var collisionInfo;
- var collisionInfos = [];
- var collision = false;
- for( var i = 0; i < steps; i++ )
- {
- checkPos = [ tilePos[0], tilePos[1] ];
- checkPos[stepIndex] = startTile + mod + i * mod;
- checkSize = [ tileSize[0], tileSize[1] ];
- checkSize[stepIndex] = 1;
- collisionInfo = this.isAreaWall( checkPos[0], checkPos[1], checkSize[0], checkSize[1], layers, checkNPC );
- if(collisionInfo.collision)
- {
- if(stopOnFirst)
- {
- return { steps: i + 1, collision: true, collisions: [collisionInfo] };
- }
- else
- {
- collisionInfos[i] = collisionInfo;
- collision = true;
- }
- }
- }
- }
- return { steps: i, collision: collision, collisions: collisionInfos };
- },
- /* collideMovement calls isRectWall with the right parameters and calculates the new move vector that should be applied
- @ sprite (Phaser.Sprite) : the sprite to check the collision for
- @ moveVector (array) : array of the x/y movement that is desired
- @ layers (Phaser.Group/Array of Phaser.TilemapLayer) : the layers of the map to check
- @ checkNPC (boolean) : if the function should check for NPC bounding boxes intersecting with the sprite
- returns object
- { newMoveVector, rectCollisionInfo }
- @ newMoveVector (array) : x/y movement that should be applied
- @ rectCollisionInfo (array of objects) : returns of isRectWall
- */
- collideMovement: function(sprite,moveVector,layers,checkNPC)
- {
- var axisOrder = [ "x", "y" ];
- var indexOrder = [ 0, 1 ];
- if( Math.abs(moveVector[1]) > Math.abs(moveVector[0]) )
- {
- axisOrder = [ "y", "x" ];
- indexOrder = [ 1, 0 ];
- }
- var pos = [ sprite.worldX, sprite.worldY ];
- var size = [ sprite.worldWidth, sprite.worldHeight ];
- var centerPos = [ sprite.worldX + size[0] / 2, sprite.worldY + size[1] / 2 ];
- var checkSize = [ sprite.worldWidth + ( sprite.worldX % 1 === 0 ? 0 : 1 ), sprite.worldHeight + ( sprite.worldY % 1 === 0 ? 0 : 1 ) ];
- var rectCollisionInfo = [];
- var newMoveVector = [0,0];
- var other, nAxis, moveDistance, tilePos, axis, nm, m, mod, move, direction, inside, outside, start, end, rectSize, checkPos, firstCollision, collidedTile, returnObject = {};
- for( var i = 0, l = moveVector.length; i < l; i++ )
- {
- m = indexOrder[i];
- other = ( i === 0 ? 1 : 0 );
- axis = axisOrder[i];
- nm = indexOrder[other];
- nAxis = axisOrder[other];
- move = moveVector[m];
- if( move === 0 ) { continue; }
- mod = ( move < 0 ? -1 : 1 );
- if( axisOrder[i] === "x" )
- {
- direction = ( mod === -1 ? 3 : 1 );
- }
- else
- {
- direction = ( mod === -1 ? 0 : 2 );
- }
- inside = centerPos[m] + size[m] / 2 * mod;
- outside = inside + move;
- start = ( mod === -1 ? outside : inside );
- end = ( mod === -1 ? inside : outside );
- rectSize = [];
- rectSize[m] = end - start;
- rectSize[nm] = checkSize[nm];
- checkPos = [ pos[0], pos[1] ];
- checkPos[m] = start;
- rectCollisionInfo[m] = this.isRectWall(checkPos[0], checkPos[1], rectSize[0], rectSize[1], direction, layers, checkNPC, false);
- //rectCollisionInfo = collisionInfo;
- if(rectCollisionInfo[m].collision)
- {
- firstCollision = rectCollisionInfo[m].collisions[0];
- if(firstCollision.tileCollided)
- {
- collidedTile = firstCollision.tileCollision[0][0].tileCollision[0].tile;
- tilePos = collidedTile[axis] + ( mod === 1 ? 0 : 1 );
- moveDistance = tilePos - inside;
- newMoveVector[m] = moveDistance;
- }
- }
- else
- {
- newMoveVector[m] = moveVector[m];
- }
- }
- returnObject.newMoveVector = newMoveVector;
- returnObject.rectCollisionInfo = rectCollisionInfo;
- return returnObject;
- },
- /* doMove just calls collideMovement and applies the return vector
- @ sprite (Phaser.Sprite) : the sprite to move
- @ moveVector (array) : x/y desired movement
- @ layers (Phaser.Group/Array of Phaser.TilemapLayer) : the layers of the map to check
- @ checkNPC (boolean) : if the function should check for NPC bounding boxes intersecting with the sprite during the movement
- returns nothing
- */
- doMove: function(sprite,newMoveVector,layers,checkNPC)
- {
- var result = this.collideMovement(sprite,newMoveVector,layers,checkNPC);
- sprite.worldX += result.newMoveVector[0];
- sprite.worldY += result.newMoveVector[1];
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement