Skip to content

Instantly share code, notes, and snippets.

@Blecki
Created April 23, 2012 06:27
Show Gist options
  • Save Blecki/2469125 to your computer and use it in GitHub Desktop.
Save Blecki/2469125 to your computer and use it in GitHub Desktop.
package
{
import Box2D.Collision.Shapes.b2PolygonShape;
import Box2D.Common.Math.b2Vec2;
import Box2D.Dynamics.b2Body;
import Box2D.Dynamics.b2BodyDef;
import Box2D.Dynamics.b2FixtureDef;
import flash.display.BitmapData;
import flash.display.GraphicsBitmapFill;
import flash.geom.Point;
import flash.geom.Rectangle;
import net.flashpunk.Entity;
import net.flashpunk.graphics.Graphiclist;
import net.flashpunk.graphics.Image;
import net.flashpunk.graphics.Spritemap;
import net.flashpunk.masks.Hitbox;
import net.flashpunk.FP;
/**
* ...
* @author AJC
*/
public class Chunk extends Entity
{
public var traversed:Boolean = false;
public var physicsBody:b2Body = null;
public var biome:int = 0;
public var blockType:int = 0;
public var tilesWidth:Number = 0;
public var tilesHeight:Number = 0;
private static var rect:Rectangle = new Rectangle();
public var connectedChunks:Array = [];
public static var connectionOverlay:Spritemap = new Spritemap(Assets.CONNECTION_OVERLAY, 20, 20);
public function Chunk(world:TinyWorld, btype:int, worldType:int)
{
biome = FP.rand(5);
//if (btype == 0)
// blockType = FP.rand(4);
//else
blockType = btype;
var angle:Number = 0;
if (blockType == 6)
{
angle = -Math.PI / 2;
blockType = 1;
}
else if (blockType == 7)
{
angle = -Math.PI / 2;
blockType = 2;
}
switch (blockType)
{
case 0:
tilesWidth = 1;
tilesHeight = 1;
rect.x = 0;
rect.y = 0;
break;
case 1:
tilesWidth = 2;
tilesHeight = 1;
rect.x = 1;
rect.y = 0;
break;
case 2:
tilesWidth = 3;
tilesHeight = 1;
rect.x = 0;
rect.y = 1;
break;
case 3:
tilesWidth = 2;
tilesHeight = 2;
rect.x = 3;
rect.y = 0;
break;
case 4:
tilesWidth = 2;
tilesHeight = 2;
rect.x = 0;
rect.y = 0;
break;
}
rect.x *= Assets.TILE_WIDTH;
rect.y *= Assets.TILE_HEIGHT;
rect.width = tilesWidth * Assets.TILE_WIDTH;
rect.height = tilesHeight * Assets.TILE_HEIGHT;
if (blockType != 4)
{
switch (biome)
{
case 0:
rect.x += ((worldType == 0 ? 2 : 0) * Assets.TILE_WIDTH);
break;
case 1:
rect.x += ((worldType == 0 ? 7 : 5) * Assets.TILE_WIDTH);
break;
case 2:
rect.x += ((worldType == 0 ? 12 : 10) * Assets.TILE_WIDTH);
break;
case 3:
rect.y += (2 * Assets.TILE_HEIGHT);
break;
case 4:
rect.y += (2 * Assets.TILE_HEIGHT);
rect.x += (5 * Assets.TILE_WIDTH);
}
}
rect.y += worldType * (Assets.TILE_HEIGHT * 4);
var image:Image = new Image(Assets.WORLDTILES, new Rectangle(rect.x, rect.y, rect.width, rect.height));
var bodyDef:b2BodyDef = new b2BodyDef();
physicsBody = world.physicsWorld.CreateBody(bodyDef);
physicsBody.SetUserData(this);
physicsBody.SetType(b2Body.b2_dynamicBody);
//var image:Image = new Image(new BitmapData(width * 16, height * 16, false, 0xFFFFFFFF));
image.originX = (tilesWidth * Assets.TILE_WIDTH) / 2;// + (tilesWidth % 2 == 1 ? -(Assets.TILE_WIDTH / 2) : 0);
image.originY = (tilesHeight * Assets.TILE_HEIGHT) / 2;// + (tilesHeight % 2 == 1 ? -(Assets.TILE_HEIGHT / 2) : 0);
graphic = image;
var boxShape:b2PolygonShape = new b2PolygonShape();
boxShape.SetAsBox(tilesWidth/2, tilesHeight/2);
//for each (var vertex:b2Vec2 in boxShape.GetVertices())
//{
// if (tilesWidth % 2 == 1) vertex.x += 0.5;
// if (tilesHeight % 2 == 1) vertex.y += 0.5;
//}
var fixtureDef:b2FixtureDef = new b2FixtureDef();
fixtureDef.shape = boxShape;
fixtureDef.density = 0.2;
fixtureDef.restitution = 0.0;
physicsBody.CreateFixture(fixtureDef).SetUserData(this);
physicsBody.SetAngle(angle);
//physicsBody.SetFixedRotation(true);
//physicsBody.SetLinearDamping(0.9999);
/*var tetrimo:int = FP.rand(tetrimos.length);
for (var x:int = 0; x < 3; ++x)
for (var y:int = 0; y < 3; ++y)
if (tetrimos[tetrimo][ (y * 3) + x ] == 1) AddSquare(x - 2, y - 2, 1, 1);
*/
}
public function CalculateTargetOffset(localVec:b2Vec2):Object
{
var angle:Number = TinyWorld.AngleBetweenVectors(b2Vec2.Make(0, -1), localVec);
if (Math.abs(angle) < Math.PI * 0.25)
return {
offset: b2Vec2.Make(0, -tilesHeight / 2),
normal: b2Vec2.Make(0, -1),
frame: (tilesWidth == 1 ? 2 : 1)
}
else if (Math.abs(angle) > Math.PI * 0.75)
return {
offset: b2Vec2.Make(0, tilesHeight / 2),
normal: b2Vec2.Make(0, 1),
frame: (tilesWidth == 1 ? 2 : 1)
}
else if (angle < 0)
return {
offset: b2Vec2.Make(-tilesWidth / 2, 0),
normal: b2Vec2.Make( -1, 0),
frame: (tilesHeight == 1 ? 2 : 1)
}
else
return {
offset: b2Vec2.Make(tilesWidth / 2, 0),
normal: b2Vec2.Make(1, 0),
frame: (tilesHeight == 1 ? 2 : 1)
}
}
override public function update():void
{
(graphic as Image).angle = -physicsBody.GetAngle() * (180.0 / Math.PI);
this.x = physicsBody.GetPosition().x * Assets.TILE_WIDTH;
this.y = physicsBody.GetPosition().y * Assets.TILE_HEIGHT;
super.update();
}
private function hiliteEdge(type:int, ex:Number, ey:Number, angle:Number)
{
angle *= 90;
connectionOverlay.frame = type;
connectionOverlay.angle = angle + (graphic as Image).angle;
connectionOverlay.centerOrigin();
var pos:b2Vec2 = physicsBody.GetWorldPoint(b2Vec2.Make(ex + 0.5, ey + 0.5));
connectionOverlay.render(FP.buffer, new Point(pos.x * 20, pos.y * 20), FP.camera);
}
override public function render():void
{
super.render();
for each (var conn:Object in connectedChunks)
DrawConnectedEdge(conn.chunk, 1);
}
public function GetClassifiedRelativeAngle(chunk:Chunk):int
{
var classifyAngle:Number = (TinyWorld.normalizeAngle(chunk.physicsBody.GetAngle() - physicsBody.GetAngle()) + 2 * Math.PI)
/ (Math.PI / 2);
return ClassifyAngle(classifyAngle);
}
public function ClassifyAngle(classifyAngle:Number):int
{
var cAngle:int = 0;
if (classifyAngle < 0.5) cAngle = 0;
else if (classifyAngle < 1.5) cAngle = 1;
else if (classifyAngle < 2.5) cAngle = 0;
else if (classifyAngle < 3.5) cAngle = 1;
else if (classifyAngle < 4.5) cAngle = 0;
else if (classifyAngle < 5.5) cAngle = 1;
else if (classifyAngle < 6.5) cAngle = 0;
else if (classifyAngle < 7.5) cAngle = 1;
else if (classifyAngle < 8.5) cAngle = 0;
else if (classifyAngle < 9.5) cAngle = 1;
else cAngle = 0;
return cAngle;
}
public function makeEdge(point:b2Vec2, dir:b2Vec2, min:Number, max:Number):Object
{
point = physicsBody.GetWorldPoint(point);
dir = physicsBody.GetWorldVector(dir);
return {
start: TinyWorld.vAdd(point, TinyWorld.Multiply(dir, min)),
end: TinyWorld.vAdd(point, TinyWorld.Multiply(dir, max)),
point: point,
dir: dir,
min: min,
max: max
};
}
public function FindConnectedEdgeLine(chunk:Chunk):Object
{
var otherRelativePosition:b2Vec2 = physicsBody.GetLocalPoint(chunk.physicsBody.GetPosition());
var cAngle:int = GetClassifiedRelativeAngle(chunk);
var otherEdgeLength:Number = 0;
if (otherRelativePosition.x < - (tilesWidth / 2) + 0.5)
{
if (cAngle == 0) otherEdgeLength = chunk.tilesHeight;
else otherEdgeLength = chunk.tilesWidth;
var edgeMin:Number = Math.max(otherRelativePosition.y - (otherEdgeLength / 2), -(tilesHeight / 2));
var edgeMax:Number = Math.min(otherRelativePosition.y + (otherEdgeLength / 2), (tilesHeight / 2));
if (edgeMin + 0.5 < edgeMax) return makeEdge(
b2Vec2.Make(-(tilesWidth/2), 0), b2Vec2.Make(0, 1), edgeMin, edgeMax);
}
if (otherRelativePosition.x > (tilesWidth / 2) - 0.5)
{
if (cAngle == 0) otherEdgeLength = chunk.tilesHeight;
else otherEdgeLength = chunk.tilesWidth;
var edgeMin:Number = Math.max(otherRelativePosition.y - (otherEdgeLength / 2), -(tilesHeight / 2));
var edgeMax:Number = Math.min(otherRelativePosition.y + (otherEdgeLength / 2), (tilesHeight / 2));
if (edgeMin + 0.5 < edgeMax) return makeEdge(
b2Vec2.Make((tilesWidth / 2), 0), b2Vec2.Make(0, 1), edgeMin, edgeMax);
}
if (otherRelativePosition.y < -(tilesHeight / 2) + 0.5)
{
if (cAngle == 1) otherEdgeLength = chunk.tilesHeight;
else otherEdgeLength = chunk.tilesWidth;
var edgeMin:Number = Math.max(otherRelativePosition.x - (otherEdgeLength / 2), -(tilesWidth / 2));
var edgeMax:Number = Math.min(otherRelativePosition.x + (otherEdgeLength / 2), (tilesWidth / 2));
if (edgeMin + 0.5 < edgeMax) return makeEdge(
b2Vec2.Make(0, -(tilesHeight / 2)), b2Vec2.Make(1, 0), edgeMin, edgeMax);
}
if (otherRelativePosition.y > (tilesHeight / 2) - 0.5)
{
if (cAngle == 1) otherEdgeLength = chunk.tilesHeight;
else otherEdgeLength = chunk.tilesWidth;
var edgeMin:Number = Math.max(otherRelativePosition.x - (otherEdgeLength / 2), -(tilesWidth / 2));
var edgeMax:Number = Math.min(otherRelativePosition.x + (otherEdgeLength / 2), (tilesWidth / 2));
if (edgeMin + 0.5 < edgeMax) return makeEdge(
b2Vec2.Make(0, (tilesHeight / 2)), b2Vec2.Make(1, 0), edgeMin, edgeMax);
}
return null;
}
public function DrawConnectedEdge(chunk:Chunk, type:int):void
{
var otherRelativePosition:b2Vec2 = physicsBody.GetLocalPoint(chunk.physicsBody.GetPosition());
var cAngle:int = GetClassifiedRelativeAngle(chunk);
var otherEdgeLength:Number = 0;
if (otherRelativePosition.x < - (tilesWidth / 2) + 0.5)
{
if (cAngle == 0) otherEdgeLength = chunk.tilesHeight;
else otherEdgeLength = chunk.tilesWidth;
var edgeMin:Number = Math.max(otherRelativePosition.y - (otherEdgeLength / 2), -(tilesHeight / 2));
var edgeMax:Number = Math.min(otherRelativePosition.y + (otherEdgeLength / 2), (tilesHeight / 2));
while (edgeMin + 0.5 < edgeMax)
{
hiliteEdge(type, -(tilesWidth / 2), edgeMin, 1);
edgeMin += 1;
}
}
if (otherRelativePosition.x > (tilesWidth / 2) - 0.5)
{
if (cAngle == 0) otherEdgeLength = chunk.tilesHeight;
else otherEdgeLength = chunk.tilesWidth;
var edgeMin:Number = Math.max(otherRelativePosition.y - (otherEdgeLength / 2), -(tilesHeight / 2));
var edgeMax:Number = Math.min(otherRelativePosition.y + (otherEdgeLength / 2), (tilesHeight / 2));
while (edgeMin + 0.5 < edgeMax)
{
hiliteEdge(type, (tilesWidth / 2) - 1, edgeMin, -1);
edgeMin += 1;
}
}
if (otherRelativePosition.y < -(tilesHeight / 2) + 0.5)
{
if (cAngle == 1) otherEdgeLength = chunk.tilesHeight;
else otherEdgeLength = chunk.tilesWidth;
var edgeMin:Number = Math.max(otherRelativePosition.x - (otherEdgeLength / 2), -(tilesWidth / 2));
var edgeMax:Number = Math.min(otherRelativePosition.x + (otherEdgeLength / 2), (tilesWidth / 2));
while (edgeMin + 0.5 < edgeMax)
{
hiliteEdge(type, edgeMin, -(tilesHeight / 2), 0);
edgeMin += 1;
}
}
if (otherRelativePosition.y > (tilesHeight / 2) - 0.5)
{
if (cAngle == 1) otherEdgeLength = chunk.tilesHeight;
else otherEdgeLength = chunk.tilesWidth;
var edgeMin:Number = Math.max(otherRelativePosition.x - (otherEdgeLength / 2), -(tilesWidth / 2));
var edgeMax:Number = Math.min(otherRelativePosition.x + (otherEdgeLength / 2), (tilesWidth / 2));
while (edgeMin + 0.5 < edgeMax)
{
hiliteEdge(type, edgeMin, (tilesHeight / 2) - 1, 2);
edgeMin += 1;
}
}
}
private function IsOdd(x:Number):Boolean { return x % 2 == 1; }
public function ClearSelected():void
{
(graphic as Image).color = 0xFFFFFFFF;
}
public function SetActive():void
{
(graphic as Image).color = 0xFFFF0000;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment