Browse Source

Adds the files from the previous project. Adds buttons to the view :D!

master
Joshua Moerman 10 years ago
parent
commit
647265895f
  1. 65
      BoxCar2D.xcodeproj/project.pbxproj
  2. 257
      GLEssentials/Car.cpp
  3. 26
      GLEssentials/Car.h
  4. 156
      GLEssentials/Drawer.cpp
  5. 66
      GLEssentials/Drawer.h
  6. 22
      GLEssentials/Fractal-iOS.fsh
  7. 18
      GLEssentials/Fractal-iOS.vsh
  8. 26
      GLEssentials/Fractal.fsh
  9. 18
      GLEssentials/Fractal.vsh
  10. 2
      GLEssentials/Game.h
  11. 181
      GLEssentials/Game.mm
  12. 19
      GLEssentials/OSX/GLView.m
  13. 114
      GLEssentials/Path.cpp
  14. 27
      GLEssentials/Path.h
  15. 7
      GLEssentials/iOS/ViewController.m
  16. 8
      GLEssentials/plain-iOS.fsh
  17. 16
      GLEssentials/plain-iOS.vsh
  18. 10
      GLEssentials/plain.fsh
  19. 16
      GLEssentials/plain.vsh
  20. 4
      Podfile

65
BoxCar2D.xcodeproj/project.pbxproj

@ -7,8 +7,16 @@
objects = {
/* Begin PBXBuildFile section */
4280D42C18E831C900E4CDFB /* Fractal-iOS.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 4280D42818E831A900E4CDFB /* Fractal-iOS.fsh */; };
4280D42D18E831D200E4CDFB /* Fractal-iOS.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 4280D42918E831A900E4CDFB /* Fractal-iOS.vsh */; };
42409A2218EAD10900B43925 /* Car.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42409A1A18EAD10900B43925 /* Car.cpp */; };
42409A2318EAD10900B43925 /* Car.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42409A1A18EAD10900B43925 /* Car.cpp */; };
42409A2418EAD10900B43925 /* Drawer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42409A1C18EAD10900B43925 /* Drawer.cpp */; };
42409A2518EAD10900B43925 /* Drawer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42409A1C18EAD10900B43925 /* Drawer.cpp */; };
42409A2618EAD10900B43925 /* Path.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42409A1E18EAD10900B43925 /* Path.cpp */; };
42409A2718EAD10900B43925 /* Path.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42409A1E18EAD10900B43925 /* Path.cpp */; };
42409A2818EAD10900B43925 /* plain.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 42409A2018EAD10900B43925 /* plain.fsh */; };
42409A2A18EAD10900B43925 /* plain.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 42409A2118EAD10900B43925 /* plain.vsh */; };
42409A2F18EAD36000B43925 /* plain-iOS.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 42409A2C18EAD36000B43925 /* plain-iOS.fsh */; };
42409A3118EAD36000B43925 /* plain-iOS.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 42409A2D18EAD36000B43925 /* plain-iOS.vsh */; };
4280D42F18E831D200E4CDFB /* Main_iPad.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4280D41C18E8311400E4CDFB /* Main_iPad.storyboard */; };
4280D43018E831D200E4CDFB /* Main_iPhone.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4280D41D18E8311400E4CDFB /* Main_iPhone.storyboard */; };
4280D43118E8321100E4CDFB /* Game.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4295A2DF18CB68A400A58D8F /* Game.mm */; };
@ -22,8 +30,6 @@
4295A2E018CB68A400A58D8F /* Game.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4295A2DF18CB68A400A58D8F /* Game.mm */; };
4295A2EB18CBB0F700A58D8F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4295A2EA18CBB0F700A58D8F /* main.m */; };
4295A2F318CBB22800A58D8F /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4295A2F218CBB22800A58D8F /* MainMenu.xib */; };
4295A2FA18CBC15000A58D8F /* Fractal.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 4295A2F618CBBFF100A58D8F /* Fractal.vsh */; };
4295A2FB18CBC15000A58D8F /* Fractal.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 4295A2F818CBC00500A58D8F /* Fractal.fsh */; };
6869D170D88D43F687C89757 /* libPods-iOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5916B6726FF14B41B517EB12 /* libPods-iOS.a */; };
D0B1A810E3574AD991F6A585 /* libPods-OSX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6DA27C28573F4442857789CE /* libPods-OSX.a */; };
/* End PBXBuildFile section */
@ -31,6 +37,16 @@
/* Begin PBXFileReference section */
152FC1C248414F0B90540EC3 /* Pods-iOS.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-iOS.xcconfig"; path = "Pods/Pods-iOS.xcconfig"; sourceTree = "<group>"; };
3A1598D311B9DDB0001E7AB5 /* BoxCar2D.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BoxCar2D.app; sourceTree = BUILT_PRODUCTS_DIR; };
42409A1A18EAD10900B43925 /* Car.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Car.cpp; path = GLEssentials/Car.cpp; sourceTree = "<group>"; };
42409A1B18EAD10900B43925 /* Car.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Car.h; path = GLEssentials/Car.h; sourceTree = "<group>"; };
42409A1C18EAD10900B43925 /* Drawer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Drawer.cpp; path = GLEssentials/Drawer.cpp; sourceTree = "<group>"; };
42409A1D18EAD10900B43925 /* Drawer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Drawer.h; path = GLEssentials/Drawer.h; sourceTree = "<group>"; };
42409A1E18EAD10900B43925 /* Path.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Path.cpp; path = GLEssentials/Path.cpp; sourceTree = "<group>"; };
42409A1F18EAD10900B43925 /* Path.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Path.h; path = GLEssentials/Path.h; sourceTree = "<group>"; };
42409A2018EAD10900B43925 /* plain.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; name = plain.fsh; path = GLEssentials/plain.fsh; sourceTree = "<group>"; };
42409A2118EAD10900B43925 /* plain.vsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; name = plain.vsh; path = GLEssentials/plain.vsh; sourceTree = "<group>"; };
42409A2C18EAD36000B43925 /* plain-iOS.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; name = "plain-iOS.fsh"; path = "GLEssentials/plain-iOS.fsh"; sourceTree = "<group>"; };
42409A2D18EAD36000B43925 /* plain-iOS.vsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; name = "plain-iOS.vsh"; path = "GLEssentials/plain-iOS.vsh"; sourceTree = "<group>"; };
4280D3EA18E8307A00E4CDFB /* BoxCar2D.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BoxCar2D.app; sourceTree = BUILT_PRODUCTS_DIR; };
4280D3EC18E8307A00E4CDFB /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
4280D3EE18E8307A00E4CDFB /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
@ -44,8 +60,6 @@
4280D41E18E8311400E4CDFB /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = GLEssentials/iOS/main.m; sourceTree = SOURCE_ROOT; };
4280D41F18E8311400E4CDFB /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ViewController.h; path = GLEssentials/iOS/ViewController.h; sourceTree = SOURCE_ROOT; };
4280D42018E8311400E4CDFB /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ViewController.m; path = GLEssentials/iOS/ViewController.m; sourceTree = SOURCE_ROOT; };
4280D42818E831A900E4CDFB /* Fractal-iOS.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; name = "Fractal-iOS.fsh"; path = "GLEssentials/Fractal-iOS.fsh"; sourceTree = "<group>"; };
4280D42918E831A900E4CDFB /* Fractal-iOS.vsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; name = "Fractal-iOS.vsh"; path = "GLEssentials/Fractal-iOS.vsh"; sourceTree = "<group>"; };
4280D43718E839C100E4CDFB /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = GLEssentials/Images.xcassets; sourceTree = "<group>"; };
4295A2C218CB4E5100A58D8F /* FullscreenWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FullscreenWindow.h; path = GLEssentials/OSX/FullscreenWindow.h; sourceTree = "<group>"; };
4295A2C318CB4E5100A58D8F /* FullscreenWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FullscreenWindow.m; path = GLEssentials/OSX/FullscreenWindow.m; sourceTree = "<group>"; };
@ -58,8 +72,6 @@
4295A2EA18CBB0F700A58D8F /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = GLEssentials/OSX/main.m; sourceTree = "<group>"; };
4295A2F018CBB1D200A58D8F /* BoxCar2D-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "BoxCar2D-Info.plist"; path = "GLEssentials/OSX/BoxCar2D-Info.plist"; sourceTree = "<group>"; };
4295A2F218CBB22800A58D8F /* MainMenu.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = MainMenu.xib; path = GLEssentials/OSX/MainMenu.xib; sourceTree = "<group>"; };
4295A2F618CBBFF100A58D8F /* Fractal.vsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; name = Fractal.vsh; path = GLEssentials/Fractal.vsh; sourceTree = "<group>"; };
4295A2F818CBC00500A58D8F /* Fractal.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; name = Fractal.fsh; path = GLEssentials/Fractal.fsh; sourceTree = "<group>"; };
5916B6726FF14B41B517EB12 /* libPods-iOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-iOS.a"; sourceTree = BUILT_PRODUCTS_DIR; };
6DA27C28573F4442857789CE /* libPods-OSX.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-OSX.a"; sourceTree = BUILT_PRODUCTS_DIR; };
FE3E0DDD70A6476884E69727 /* Pods-OSX.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OSX.xcconfig"; path = "Pods/Pods-OSX.xcconfig"; sourceTree = "<group>"; };
@ -85,18 +97,24 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
080E96DDFE201D6D7F000001 /* GLEssentials */ = {
080E96DDFE201D6D7F000001 /* BoxCar2D */ = {
isa = PBXGroup;
children = (
42409A2C18EAD36000B43925 /* plain-iOS.fsh */,
42409A2D18EAD36000B43925 /* plain-iOS.vsh */,
42409A2018EAD10900B43925 /* plain.fsh */,
42409A2118EAD10900B43925 /* plain.vsh */,
42409A1A18EAD10900B43925 /* Car.cpp */,
42409A1B18EAD10900B43925 /* Car.h */,
42409A1C18EAD10900B43925 /* Drawer.cpp */,
42409A1D18EAD10900B43925 /* Drawer.h */,
42409A1E18EAD10900B43925 /* Path.cpp */,
42409A1F18EAD10900B43925 /* Path.h */,
4295A2DE18CB68A400A58D8F /* Game.h */,
4295A2DF18CB68A400A58D8F /* Game.mm */,
4295A2F618CBBFF100A58D8F /* Fractal.vsh */,
4295A2F818CBC00500A58D8F /* Fractal.fsh */,
4280D42818E831A900E4CDFB /* Fractal-iOS.fsh */,
4280D42918E831A900E4CDFB /* Fractal-iOS.vsh */,
4280D42718E8314A00E4CDFB /* Supporting Files */,
);
name = GLEssentials;
name = BoxCar2D;
sourceTree = "<group>";
};
19C28FACFE9D520D11CA2CBB /* Products */ = {
@ -112,7 +130,7 @@
isa = PBXGroup;
children = (
4280D43718E839C100E4CDFB /* Images.xcassets */,
080E96DDFE201D6D7F000001 /* GLEssentials */,
080E96DDFE201D6D7F000001 /* BoxCar2D */,
4280D3EB18E8307A00E4CDFB /* Frameworks */,
19C28FACFE9D520D11CA2CBB /* Products */,
FE3E0DDD70A6476884E69727 /* Pods-OSX.xcconfig */,
@ -251,10 +269,10 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
42409A2F18EAD36000B43925 /* plain-iOS.fsh in Resources */,
4280D42F18E831D200E4CDFB /* Main_iPad.storyboard in Resources */,
42409A3118EAD36000B43925 /* plain-iOS.vsh in Resources */,
4280D43018E831D200E4CDFB /* Main_iPhone.storyboard in Resources */,
4280D42D18E831D200E4CDFB /* Fractal-iOS.vsh in Resources */,
4280D42C18E831C900E4CDFB /* Fractal-iOS.fsh in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -264,8 +282,8 @@
files = (
4280D43818E839C100E4CDFB /* Images.xcassets in Resources */,
4295A2F318CBB22800A58D8F /* MainMenu.xib in Resources */,
4295A2FA18CBC15000A58D8F /* Fractal.vsh in Resources */,
4295A2FB18CBC15000A58D8F /* Fractal.fsh in Resources */,
42409A2A18EAD10900B43925 /* plain.vsh in Resources */,
42409A2818EAD10900B43925 /* plain.fsh in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -339,10 +357,13 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
42409A2518EAD10900B43925 /* Drawer.cpp in Sources */,
4280D43218E8321100E4CDFB /* main.m in Sources */,
4280D43318E8321100E4CDFB /* AppDelegate.m in Sources */,
42409A2718EAD10900B43925 /* Path.cpp in Sources */,
4280D43418E8321100E4CDFB /* ViewController.m in Sources */,
4280D43118E8321100E4CDFB /* Game.mm in Sources */,
42409A2318EAD10900B43925 /* Car.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -350,10 +371,13 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
42409A2218EAD10900B43925 /* Car.cpp in Sources */,
4295A2EB18CBB0F700A58D8F /* main.m in Sources */,
4295A2CA18CB4E5100A58D8F /* FullscreenWindow.m in Sources */,
4295A2CB18CB4E5100A58D8F /* GLView.m in Sources */,
42409A2418EAD10900B43925 /* Drawer.cpp in Sources */,
4295A2CC18CB4E5100A58D8F /* WindowController.m in Sources */,
42409A2618EAD10900B43925 /* Path.cpp in Sources */,
4295A2E018CB68A400A58D8F /* Game.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -447,7 +471,6 @@
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
GCC_C_LANGUAGE_STANDARD = c99;
GCC_OPTIMIZATION_LEVEL = 0;
@ -474,10 +497,10 @@
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = c99;
GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1";
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;

257
GLEssentials/Car.cpp

@ -0,0 +1,257 @@
//
// Car.cpp
// OSXGLEssentials
//
// Created by Joshua Moerman on 10/03/14.
//
//
#include "Car.h"
#include <vector>
#include <random>
#include <functional>
#include <iostream>
static float get_rand(float min, float max){
return min + (rand() / float(RAND_MAX)) * (max - min);
}
struct WheelGenome {
float speed;
float radius;
};
std::ostream & operator<<(std::ostream& out, WheelGenome const & g){
return out << "(W speed=" << g.speed << " radius=" << g.radius << ")";
}
struct StickGenome {
float angle;
float limit;
float width;
float length;
std::vector<WheelGenome> wheel;
std::vector<StickGenome> sticks;
};
std::ostream & operator<<(std::ostream& out, StickGenome const & g){
out << "(S angle=" << g.angle << " limit=" << g.limit << " width=" << g.width << " length=" << g.length;
out << " wheel=";
for(auto&& w : g.wheel) out << w;
out << " sticks=";
for(auto&& s : g.sticks) out << s;
return out << ")";
}
struct CarGenome {
std::vector<StickGenome> sticks;
};
std::ostream & operator<<(std::ostream& out, CarGenome const & g){
out << "(C sticks=";
for(auto&& s : g.sticks) out << s;
return out << ")";
}
struct GenomeCreator {
std::mt19937 generator{37};
std::uniform_real_distribution<float> distribution_float{0.0, 1.0};
std::uniform_int_distribution<int> distribution_int{0, 4};
std::uniform_int_distribution<int> distribution_bool{0, 1};
std::function<float()> r = std::bind(distribution_float, generator);
std::function<int()> s = std::bind(distribution_int, generator);
std::function<int()> w = std::bind(distribution_bool, generator);
float min = 0.05f;
WheelGenome wheel(){
WheelGenome g;
g.speed = r() * 20 + 10;
g.radius = r() + min;
return g;
}
StickGenome stick(){
StickGenome g;
g.angle = r() * 2 * M_PI;
g.limit = r() * 0.05f * M_PI;
g.width = r() * 0.2f + min;
g.length = r() * 5 + 1;
if(w()){
g.wheel.push_back(wheel());
} else {
auto sticks = s() - 1;
while(sticks-- > 0){
g.sticks.push_back(stick());
}
}
return g;
}
CarGenome car(){
CarGenome g;
auto sticks = s() + 1;
while(sticks-- > 0){
g.sticks.push_back(stick());
}
return g;
}
};
static GenomeCreator creator;
struct CarBuilder {
b2World & world;
b2CircleShape wheelShape;
b2FixtureDef wheelFixture;
b2BodyDef wheelBody;
b2PolygonShape stickShape;
b2FixtureDef stickFixture;
b2BodyDef stickBody;
b2PolygonShape boxShape;
b2FixtureDef boxFixture;
b2BodyDef boxBody;
b2RevoluteJointDef motor;
b2RevoluteJointDef stickJoint;
std::vector<b2Body*> created_parts;
CarBuilder(b2World & world_)
: world(world_)
{
// constants
wheelFixture.shape = &wheelShape;
wheelFixture.density = 1.0f;
wheelFixture.friction = 1.0f;
wheelFixture.restitution = 0.1f;
wheelFixture.filter.groupIndex = -1;
wheelBody.type = b2_dynamicBody;
stickFixture.shape = &stickShape;
stickFixture.density = 2.0f;
stickFixture.friction = 0.7f;
stickFixture.filter.groupIndex = -1;
stickBody.type = b2_dynamicBody;
boxShape.SetAsBox(0.05, 0.05);
boxFixture.shape = &boxShape;
boxFixture.density = 2000.0f;
boxFixture.friction = 0.3f;
boxFixture.filter.groupIndex = -1;
boxBody.type = b2_dynamicBody;
motor.maxMotorTorque = 100;
motor.enableMotor = true;
//stickJoint.enableLimit = true;
stickJoint.enableMotor = true;
stickJoint.maxMotorTorque = 1000;
stickJoint.motorSpeed = get_rand(-1, 2);
}
b2Body * createWheel(WheelGenome const & g){
wheelShape.m_radius = g.radius;
auto body = world.CreateBody(&wheelBody);
body->CreateFixture(&wheelFixture);
created_parts.push_back(body);
return body;
}
b2Body * createStick(StickGenome const & g){
stickShape.SetAsBox(0.5 * g.length, 0.5 * g.width);
auto body = world.CreateBody(&stickBody);
body->CreateFixture(&stickFixture);
created_parts.push_back(body);
for(auto&& wg : g.wheel){
auto wheel = createWheel(wg);
wheel->SetTransform({g.length, 0.0}, 0);
motor.localAnchorA = {0.5f * g.length, 0};
motor.bodyA = body;
motor.bodyB = wheel;
motor.motorSpeed = -wg.speed; // CCW
world.CreateJoint(&motor);
}
for(auto&& sg : g.sticks){
auto stick = createStick(sg);
float startAngle = sg.angle;
stick->SetTransform({g.length, 0.0}, startAngle);
stickJoint.localAnchorA = {0.5f * g.length, 0};
stickJoint.localAnchorB = {-0.5f * sg.length, 0};
stickJoint.bodyA = body;
stickJoint.bodyB = stick;
stickJoint.lowerAngle = startAngle - sg.limit;
stickJoint.upperAngle = startAngle + sg.limit;
stickJoint.referenceAngle = startAngle;
world.CreateJoint(&stickJoint);
}
return body;
}
b2Body * createCar(CarGenome const & g){
created_parts.clear();
auto body = world.CreateBody(&boxBody);
body->CreateFixture(&boxFixture);
created_parts.push_back(body);
for(auto&& sg : g.sticks){
auto stick = createStick(sg);
float startAngle = sg.angle;
stick->SetTransform({sg.length, 0.0}, startAngle);
stickJoint.localAnchorA = {0, 0};
stickJoint.localAnchorB = {-0.5f * sg.length, 0};
stickJoint.bodyA = body;
stickJoint.bodyB = stick;
stickJoint.lowerAngle = startAngle - sg.limit;
stickJoint.upperAngle = startAngle + sg.limit;
stickJoint.referenceAngle = startAngle;
world.CreateJoint(&stickJoint);
}
return body;
}
};
Car::Car(b2World & world_)
: world(world_)
{
auto genome = creator.car();
CarBuilder builder(world);
body = builder.createCar(genome);
parts.swap(builder.created_parts);
}
Car::Car(Car&& c)
: world(c.world)
, body(c.body)
, parts(std::move(c.parts))
{}
Car::~Car(){
for(auto&& p : parts){
world.DestroyBody(p);
}
}
b2Vec2 Car::getPosition() const {
return body->GetPosition();
}

26
GLEssentials/Car.h

@ -0,0 +1,26 @@
//
// Car.h
// OSXGLEssentials
//
// Created by Joshua Moerman on 10/03/14.
//
//
#pragma once
#include <Box2D/Box2D.h>
#include <vector>
struct Car {
Car(b2World & world);
Car(Car&& c);
Car(Car const & c) = delete;
~Car();
b2Vec2 getPosition() const;
private:
b2World & world;
b2Body * body = nullptr;
std::vector<b2Body*> parts;
};

156
GLEssentials/Drawer.cpp

@ -0,0 +1,156 @@
//
// Drawer.cpp
// OSXGLEssentials
//
// Created by Joshua Moerman on 10/03/14.
//
//
#include "Drawer.h"
#include <moggle/math/projection.hpp>
#include <moggle/math/transformation.hpp>
using namespace moggle;
// We need to pass relative addresses to opengl
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
// We may assume this at some point
static_assert(sizeof(Vertex) == 6*4, "wrong size");
// Circles
static constexpr size_t circleVertices = 13;
static const Vertex::Position (&getCircle())[circleVertices]{
static Vertex::Position vertices[circleVertices];
static bool shouldInit = true;
if(shouldInit){
for(int i = 0; i < circleVertices;++i){
auto phi = 2 * i / double(circleVertices-1) * M_PI;
vertices[i] = {cos(phi), -sin(phi)};
}
shouldInit = false;
}
return vertices;
}
static const float viewSize = 20.0;
#if TARGET_OS_IPHONE
static const char * file = "/plain-iOS";
#else
static const char * file = "/plain";
#endif
// Implementation
Drawer::Drawer(std::string const & bundle){
gl::enable(GL_BLEND);
gl::blend_function(GL_SRC_ALPHA, GL_ONE);
gl::clear_color(0.2f, 0.05f, 0.05f, 1.0f);
projection = projection_matrices::orthographic(-viewSize, viewSize, -viewSize, viewSize, -1, 1);
auto vertex = shader::from_file(shader_type::vertex, bundle + file + ".vsh");
auto fragment = shader::from_file(shader_type::fragment, bundle + file + ".fsh");
program.attach(vertex);
program.attach(fragment);
program.bind_attribute(0, "position");
program.bind_attribute(1, "color");
program.link();
gl::generate_vertex_arrays(1, &vao);
gl::bind_vertex_array(vao);
gl::generate_buffers(1, &buf);
gl::bind_buffer(GL_ARRAY_BUFFER, buf);
}
void Drawer::draw(){
// bug when going to fullscreen
// possibly related http://lists.apple.com/archives/mac-opengl/2012/Jul/msg00041.html
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if(glGetError() != GL_NO_ERROR) return;
matrix4<float> mvp = projection * transformation_matrices::translate(-camera);
program.use();
program.uniform<matrix4<float>>("mvp").set(mvp);
if(!segments.empty()){
if(verbose) printf("drawing %lu objects and %lu segments\n", sizes.size(), segments.size());
gl::bind_vertex_array(vao);
gl::bind_buffer(GL_ARRAY_BUFFER, buf);
gl::buffer_data(GL_ARRAY_BUFFER, sizeof(Vertex) * segments.size(), &segments[0], GL_STATIC_DRAW);
gl::enable_vertex_attribute_array(0);
gl::enable_vertex_attribute_array(1);
gl::vertex_attribute_pointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(0));
gl::vertex_attribute_pointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(3*4));
GLuint start = 0;
for(auto&& s : sizes){
gl::draw_arrays(GL_LINE_LOOP, start, s);
start += s;
}
}
}
void Drawer::clear(){
sizes.clear();
segments.clear();
}
void Drawer::resize(float width, float height){
auto aspect = width / height;
auto hheight = viewSize;
projection = projection_matrices::orthographic(-hheight * aspect, hheight * aspect, -hheight, hheight, -5, 5);
}
void Drawer::DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color){
if(verbose) printf("polygon (not solid)\n %d vertices\n %f %f %f\n", vertexCount, color.r, color.g, color.b);
for(int i = 0; i < vertexCount; ++i){
segments.push_back(Vertex{convert(vertices[i]), convert(color)});
}
sizes.emplace_back(vertexCount);
}
void Drawer::DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color){
if(verbose) printf("polygon (solid, deferred)\n");
DrawPolygon(vertices, vertexCount, color);
}
void Drawer::DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color){
if(verbose) printf("circle (not solid)\n at %f %f (%f)\n %f %f %f\n", center.x, center.y, radius, color.r, color.g, color.b);
for(auto&& p : getCircle()){
segments.push_back(Vertex{convert(center) + radius * p, convert(color)});
}
sizes.emplace_back(circleVertices);
}
void Drawer::DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color){
if(verbose) printf("circle (solid, deferred)\n");
segments.push_back(Vertex{convert(center) - radius * convert(axis), convert(color)});
segments.push_back(Vertex{convert(center) + radius * convert(axis), convert(color)});
sizes.push_back(2);
DrawCircle(center, radius, color);
}
void Drawer::DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color){
if(verbose) printf("segment\n %f %f -> %f %f\n %f %f %f\n", p1.x, p1.y, p2.x, p2.y, color.r, color.g, color.b);
segments.push_back(Vertex{convert(p1), convert(color)});
segments.push_back(Vertex{convert(p2), convert(color)});
sizes.emplace_back(2);
}
void Drawer::DrawTransform(const b2Transform& xf){
if(verbose) printf("transform\n");
}

66
GLEssentials/Drawer.h

@ -0,0 +1,66 @@
//
// Drawer.h
// OSXGLEssentials
//
// Created by Joshua Moerman on 10/03/14.
//
//
#pragma once
#include <Box2D/Box2D.h>
#include <moggle/core/gl.hpp>
#include <moggle/math/matrix.hpp>
#include <moggle/core/shader.hpp>
#include <vector>
struct Vertex {
using Position = moggle::vector3<float>;
using Color = moggle::vector3<float>;
Position position;
Color color;
};
inline moggle::vector3<float> convert(b2Vec2 const & p){ return {p.x, p.y, 0.0f}; }
inline moggle::vector3<float> convert(b2Color const & p){ return {p.r, p.g, p.b}; }
struct Drawer : b2Draw {
// camera position
Vertex::Position camera = {0, 0};
// print debugging info
bool verbose = false;
// bundle needed to load shaders
Drawer(std::string const & bundle);
// draw buffer
void draw();
// clear buffer
void clear();
// resize any stuff
void resize(float width, float height);
// Box 2D drawing interface
// Implementation will fill its buffers
virtual void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) override;
virtual void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) override;
virtual void DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color) override;
virtual void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color) override;
virtual void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) override;
virtual void DrawTransform(const b2Transform& xf) override;
private:
moggle::shader_program program;
moggle::matrix4<float> projection;
std::vector<Vertex> segments;
std::vector<GLuint> sizes;
GLuint vao, buf;
};

22
GLEssentials/Fractal-iOS.fsh

@ -1,22 +0,0 @@
#version 100
varying highp vec2 pos;
varying highp vec2 start;
void main(){
highp vec2 z = start;
int i = 0;
for (i = 0; i < 7; i++) {
highp vec2 zsq = z*z;
if(zsq.x + zsq.y > 16.0) break;
highp float t = zsq.x - zsq.y + pos.x;
z.y = 2.0*z.x*z.y + pos.y;
z.x = t;
}
gl_FragColor = vec4(float(i) / 7.0);
gl_FragColor.bg = 0.5 * sin(z) + 0.5;
}

18
GLEssentials/Fractal-iOS.vsh

@ -1,18 +0,0 @@
#version 100
uniform float rotation;
attribute vec4 position;
attribute vec4 color;
varying vec2 pos;
varying vec2 start;
void main(){
pos = position.xy;
pos.x -= 0.5;
start = sqrt(1.0 + 0.01 * rotation) * 0.3 * sin(vec2(0.1, 0.1337) * rotation);
gl_Position = position;
}

26
GLEssentials/Fractal.fsh

@ -1,26 +0,0 @@
#version 330
uniform float rotation;
in vec2 pos;
in vec2 start;
out vec4 fragColor;
void main(){
vec2 z = start;
int i = 0;
for (i = 0; i < 30; i++) {
vec2 zsq = z*z;
if(zsq.x + zsq.y > 16.0) break;
float t = zsq.x - zsq.y + pos.x;
z.y = 2.0*z.x*z.y + pos.y;
z.x = t;
}
fragColor = vec4(float(i) / 30.0);
fragColor.bg = 0.5 * sin(z) + 0.5;
}

18
GLEssentials/Fractal.vsh

@ -1,18 +0,0 @@
#version 330
uniform float rotation;
in vec4 position;
in vec4 color;
out vec2 pos;
out vec2 start;
void main(){
pos = position.xy;
pos.x -= 0.5;
start = sqrt(1.0 + 0.01 * rotation) * 0.3 * sin(vec2(0.1, 0.1337) * rotation);
gl_Position = position;
}

2
GLEssentials/Game.h

@ -12,5 +12,7 @@
@interface Game : NSObject
- (void)update:(float)dt;
- (void)draw;
- (void)action:(NSString*)a;
@property (nonatomic) CGSize windowSize;
@property (nonatomic) NSArray * actions;
@end

181
GLEssentials/Game.mm

@ -7,111 +7,122 @@
//
#import "Game.h"
#include "Drawer.h"
#include "Car.h"
#include "Path.h"
#include <moggle/core/gl.hpp>
#include <Box2D/Box2D.h>
#include <string>
#include <map>
#include <functional>
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
using namespace moggle;
static int ncars = 10;
#ifdef TARGET_OS_IPHONE
NSString * file = @"Fractal-iOS";
#else
NSString * file = @"Fractal";
#endif
const GLfloat quad[] = {
// x y z, r g b
1, -1, 0, 1, 0, 0,
-1, -1, 0, 0, 1, 0,
1, 1, 0, 0, 0, 1,
-1, 1, 0, 1, 1, 1
};
static void check_shader(GLuint s){
GLint logLength;
glGetShaderiv(s, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar *log = (GLchar *)malloc(logLength);
glGetShaderInfoLog(s, logLength, &logLength, log);
NSLog(@"Shader compile log:\n%s", log);
free(log);
struct GameCPP{
std::map<std::string, std::function<void()>> actions;
bool should_regenerate = false;
int steps = 2;
std::string bundle;
Drawer drawer{bundle};
b2Vec2 gravity{0.0f, -10.0f};
b2World world{gravity};
std::vector<Car> cars;
Path path{world};
GameCPP(std::string const & bundle_)
: bundle(bundle_){
actions["regenerate"] = [this]{ should_regenerate = true; };
actions["speed"] = [this]{ steps *= 2; if(steps >= 32) steps = 2; };
path.buildUpTo(100);
create_cars();
drawer.SetFlags(b2Draw::e_shapeBit + b2Draw::e_jointBit);
world.SetDebugDraw(&drawer);
}
}
void create_cars(){
for(int i = 0; i < ncars; ++i){
cars.emplace_back(world);
}
}
void draw(){
drawer.camera = convert(getFurthest());
drawer.clear();
world.DrawDebugData();
drawer.draw();
}
void update(float dt){
if(should_regenerate){
should_regenerate = false;
cars.clear();
create_cars();
}
for(int i = 0; i < steps; ++i){
path.buildUpTo(getFurthest().x + 25);
world.Step(dt, 8, 3);
}
}
void resize(float width, float height){
drawer.resize(width, height);
}
b2Vec2 getFurthest() const {
b2Vec2 furthest = {0, 0};
for(auto&& c : cars){
auto p = c.getPosition();
if(p.x > furthest.x){
furthest = p;
}
}
return furthest;
}
};
@implementation Game{
float time;
GLuint program;
GLint uniform;
GLuint vao;
GLuint posBufferName;
GameCPP * game;
NSMutableArray * actions;
}
@synthesize windowSize, actions;
- (id)init{
if(self = [super init]){
time = 0;
program = glCreateProgram();
NSError * error = nil;
NSString * vs = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:file ofType:@"vsh"] encoding:NSASCIIStringEncoding error:&error];
NSString * fs = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:file ofType:@"fsh"] encoding:NSASCIIStringEncoding error:nil];
GLchar const * vs_cstr = [vs UTF8String];
GLchar const * fs_cstr = [fs UTF8String];
GLuint v = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(v, 1, &vs_cstr, NULL);
glCompileShader(v);
check_shader(v);
GLuint f = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(f, 1, &fs_cstr, NULL);
glCompileShader(f);
check_shader(f);
glAttachShader(program, v);
glAttachShader(program, f);
glBindAttribLocation(program, 0, "position");
glBindAttribLocation(program, 1, "color");
glLinkProgram(program);
uniform = glGetUniformLocation(program, "rotation");
NSString * path = [[NSBundle mainBundle] resourcePath];
game = new GameCPP([path UTF8String]);
actions = [NSMutableArray arrayWithCapacity: 10];
glDetachShader(program, v);
glDeleteShader(v);
glDetachShader(program, f);
glDeleteShader(f);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &posBufferName);
glBindBuffer(GL_ARRAY_BUFFER, posBufferName);
glBufferData(GL_ARRAY_BUFFER, 4*6*4, quad, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*4, BUFFER_OFFSET(0));
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*4, BUFFER_OFFSET(3*4));
for(auto&& p : game->actions){
[actions addObject:[NSString stringWithUTF8String:p.first.c_str()]];
}
}
return self;
}
- (void)update:(float)dt{
time += dt;
game->update(dt);
}
- (void)draw{
glClearColor(0.65f, 0.65f, 0.65f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(program);
glUniform1f(uniform, time);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
game->draw();
}
- (void)action:(NSString *)a{
game->actions[[a UTF8String]]();
}
- (void)setWindowSize:(CGSize)windowSize_{
windowSize = windowSize_;
game->resize(windowSize.width, windowSize.height);
}
@end

19
GLEssentials/OSX/GLView.m

@ -123,6 +123,25 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink,
[[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
game = [[Game alloc] init];
CGFloat x = 20;
CGFloat y = 20;
for (NSString * a in game.actions) {
NSButton *myButton = [[NSButton alloc] initWithFrame:NSMakeRect(x, y, 200, 22)];
myButton.buttonType = NSMomentaryLightButton;
myButton.bezelStyle = NSRecessedBezelStyle;
myButton.title = a;
myButton.target = self;
myButton.action = @selector(action:);
myButton.wantsLayer = YES;
[self addSubview: myButton];
y += 22;
}
}
- (void) action:(NSButton*) sender{
[game action:sender.title];
}
- (void) reshape{

114
GLEssentials/Path.cpp

@ -0,0 +1,114 @@
//
// Path.cpp
// OSXGLEssentials
//
// Created by Joshua Moerman on 10/03/14.
//
//
#include "Path.h"
#include <cmath>
#include <random>
// A default thingy which makes implementing it easier. A subclass only have to
// provide new points, which will be connected (So this is not suitable for
// e.g. jumps or circles)
struct DefaultBuilder : PathBuilder {
// number of vertices in one chunk
static constexpr auto chainLength = 8;
DefaultBuilder(b2World & world_, b2Vec2 startingPoint)
: world(world_)
, previous(startingPoint)
, current(startingPoint)
{
fixture.friction = 2.0;
}
void buildUpTo(float x) override {
b2BodyDef groundBodyDef;
groundBodyDef.position = {0.0f, -10.0f};
while(current.x < x){
auto oldPreviousPoint = previous;
b2Vec2 chainPositions[chainLength];
chainPositions[0] = current;
for(int i = 1; i < chainLength; ++i){
chainPositions[i] = next;
previous = current;
current = next;
// we always generate one more, for the b2 ghost vertices
generate_next();
}
b2ChainShape chain;
chain.CreateChain(chainPositions, chainLength);
chain.SetPrevVertex(oldPreviousPoint);
chain.SetNextVertex(next);
fixture.shape = &chain;
auto groundBody = world.CreateBody(&groundBodyDef);
groundBody->CreateFixture(&fixture);
}
}
virtual void generate_next() = 0;
protected:
std::mt19937 generator{0};
std::uniform_real_distribution<float> distribution{-1.0, 1.0};
b2World & world;
b2Vec2 previous;
b2Vec2 current;
b2Vec2 next;
b2FixtureDef fixture;
};
// Creates random terrain, roughness comes with time
struct RandomBuilder : DefaultBuilder {
RandomBuilder(b2World & world_, b2Vec2 startingPoint)
: DefaultBuilder(world_, startingPoint)
{
generate_next();
}
virtual void generate_next() override {
auto t = current.x;
float m = std::sqrt(0.001f*t + 1) - 1;
if(t <= 0) m = 0;
float slope = m * distribution(generator);
auto rot = b2Rot(slope);
next = b2Mul(rot, {10, 0}) + current;
}
};
// A flat road
struct FlatBuilder : DefaultBuilder {
FlatBuilder(b2World & world_, b2Vec2 startingPoint)
: DefaultBuilder(world_, startingPoint)
{
generate_next();
}
virtual void generate_next() override {
b2Vec2 newPiece = {10, 0};
next = newPiece + current;
}
};
Path::Path(b2World & world_)
: world(world_)
, impl(new RandomBuilder(world, {-20, 0}))
{}
void Path::buildUpTo(float x){
impl->buildUpTo(x);
}

27
GLEssentials/Path.h

@ -0,0 +1,27 @@
//
// Path.h
// OSXGLEssentials
//
// Created by Joshua Moerman on 10/03/14.
//
//
#pragma once
#include <Box2D/Box2D.h>
#include <memory>
struct PathBuilder {
virtual ~PathBuilder() = default;
virtual void buildUpTo(float x) = 0;
};
// Has a path builder object
struct Path {
Path(b2World & world);
void buildUpTo(float x);
private:
b2World & world;
std::unique_ptr<PathBuilder> impl;
};

7
GLEssentials/iOS/ViewController.m

@ -32,11 +32,12 @@
view.context = self.context;
view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
view.drawableMultisample = GLKViewDrawableMultisampleNone;
view.contentScaleFactor = 1.0;
//view.contentScaleFactor = 1.0;
self.preferredFramesPerSecond = 60;
[self setupGL];
game.windowSize = self.view.bounds.size;
}
- (void)dealloc{
@ -64,6 +65,10 @@
// Dispose of any resources that can be recreated.
}
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{
game.windowSize = self.view.bounds.size;
}
- (void)setupGL{
[EAGLContext setCurrentContext:self.context];
game = [[Game alloc] init];

8
GLEssentials/plain-iOS.fsh

@ -0,0 +1,8 @@
#version 100
varying lowp vec4 interpolated_color;
varying lowp vec4 interpolated_position;
void main(){
gl_FragColor = interpolated_color;
}

16
GLEssentials/plain-iOS.vsh

@ -0,0 +1,16 @@
#version 100
uniform mat4 mvp;
attribute vec4 position;
attribute vec4 color;
varying vec4 interpolated_color;
varying vec4 interpolated_position;
void main(){
interpolated_color = color;
interpolated_position = position;
gl_Position = mvp * position;
}

10
GLEssentials/plain.fsh

@ -0,0 +1,10 @@
#version 330
in vec4 interpolated_color;
in vec4 interpolated_position;
out vec4 fragColor;
void main(){
fragColor = interpolated_color;
}

16
GLEssentials/plain.vsh

@ -0,0 +1,16 @@
#version 330
uniform mat4 mvp;
in vec4 position;
in vec4 color;
out vec4 interpolated_color;
out vec4 interpolated_position;
void main(){
interpolated_color = color;
interpolated_position = position;
gl_Position = mvp * position;
}

4
Podfile

@ -7,13 +7,13 @@ target 'OSX' do
platform :osx, '10.9'
pod 'box2d'
pod 'moggle', :path => '../moggle'
pod 'moggle', :git => 'https://github.com/Jaxan/moggle', :tag => "0.1.0"
end
target 'iOS' do
platform :ios, '7.0'
pod 'box2d'
pod 'moggle', :path => '../moggle'
pod 'moggle', :git => 'https://github.com/Jaxan/moggle', :tag => "0.1.0"
end