00001
00002
00003
00004
00005 #include <ode/ode.h>
00006 #include "demo.hpp"
00007 #include "os.h"
00008
00009 using namespace Demo;
00010 using Flatland::pi;
00011 using Flatland::aabb;
00012 using Flatland::ContactList;
00013
00014 class ComplexApp : public App
00015 {
00016 public:
00017 ComplexApp(bool fullscreen);
00018 void InitWin();
00019 void InitGl();
00020 void Draw() const;
00021 void HandleEvents();
00022 void ProcessKeyState();
00023 void ToggleFullscreen();
00024 bool MouseMoved() const { return motion; }
00025 bool IsFullscreen() const { return fullscreen; }
00026 static int GetWidth(bool screen) { return screen ? osGetScreenWidth() : InitialWidth; }
00027 static int GetHeight(bool screen) { return screen ? osGetScreenHeight() : InitialHeight; }
00028 static const int InitialWidth = 1000;
00029 static const int InitialHeight = 600;
00030 private:
00031 void handle(const OS_Event &event);
00032 Texture helpTexture;
00033 Texture downTexture;
00034 Texture upTexture;
00035 Texture boostTexture;
00036 Texture wheelTexture;
00037 bool freeze;
00038 bool hover;
00039 bool pressed;
00040 bool fullscreen;
00041 bool motion;
00042 aabb scrollbox;
00043 vec2 scrolloffset;
00044 Wheel *wheel;
00045 Wheel *wheel2;
00046 dJointID motor;
00047 dJointID pendulumAnchor;
00048 dJointID bubbleAnchor;
00049 dJointID blockFeeder;
00050 dJointID squareWheelMotor;
00051 static void boostCallback(ContactList &contacts);
00052 static void pendulumCallback(ContactList &contacts);
00053 static void bubbleCallback(ContactList &contacts);
00054 static void feederCallback(ContactList &contacts);
00055 };
00056
00057
00058 int main(int argc, char** argv)
00059 {
00060
00061 const bool fullscreen = false;
00062 ComplexApp app(fullscreen);
00063
00064
00065 const float fps = 60;
00066 const unsigned int fDelay = (unsigned int) (1000.0f / fps);
00067
00068
00069 const float sps = 1000;
00070 const unsigned int sDelay = (unsigned int) (1000.0f / sps);
00071
00072
00073 const bool capFps = true;
00074 const bool capSps = true;
00075 osWaitVsync(1);
00076
00077
00078
00079
00080
00081
00082 const float delta = 0.25;
00083
00084
00085 const unsigned int mDelay = 2000;
00086
00087
00088 unsigned int fTime, sTime, mTime;
00089 for (fTime = sTime = mTime = osGetMilliseconds();;)
00090 {
00091
00092 app.HandleEvents();
00093
00094
00095 unsigned int time = osGetMilliseconds();
00096
00097
00098 if (!capFps || time - fTime > fDelay)
00099 {
00100 app.Draw();
00101 osSwapBuffers();
00102 fTime = time;
00103 }
00104
00105
00106 if (capSps && time - sTime < sDelay)
00107 continue;
00108 sTime = time;
00109
00110
00111 app.ProcessKeyState();
00112 app.Step(delta);
00113 app.UpdateCenter();
00114
00115
00116 if (app.IsFullscreen())
00117 {
00118 if (app.MouseMoved())
00119 {
00120 mTime = time;
00121 if (!osShowCursor(OS_QUERY))
00122 osShowCursor(OS_ENABLE);
00123 }
00124 else if (osShowCursor(OS_QUERY) && time - mTime > mDelay)
00125 {
00126 osShowCursor(OS_DISABLE);
00127 }
00128 }
00129 }
00130
00131 return 0;
00132 }
00133
00134 #define app (static_cast<ComplexApp&>(App::GetSingleton()))
00135
00136
00137 void ComplexApp::ToggleFullscreen()
00138 {
00139 osQuit();
00140 fullscreen = !fullscreen;
00141 width = GetWidth(fullscreen);
00142 height = GetHeight(fullscreen);
00143 hover = false;
00144 InitWin();
00145 InitGl();
00146 }
00147
00148
00149 void ComplexApp::HandleEvents()
00150 {
00151 motion = false;
00152 OS_Event event;
00153 while (osPollEvent(&event))
00154 handle(event);
00155 }
00156
00157
00158 void ComplexApp::handle(const OS_Event &event)
00159 {
00160 switch(event.type)
00161 {
00162 case OS_RESIZE:
00163 Resize(event.resize.width, event.resize.height);
00164 return;
00165
00166 case OS_QUIT: exit(0);
00167
00168 case OS_MOUSEBUTTONDOWN:
00169 pressed = hover && event.mouse.button == OS_BUTTON_LEFT;
00170 break;
00171
00172 case OS_MOUSEBUTTONUP:
00173 if (event.mouse.button == OS_BUTTON_LEFT)
00174 {
00175 pressed = false;
00176 if (hover)
00177 ToggleFullscreen();
00178 }
00179 break;
00180
00181 case OS_MOUSEMOTION:
00182 if (osShowCursor(OS_QUERY))
00183 {
00184 hover = event.mouse.x < TextureWidth(upTexture) + 2;
00185 hover = hover && event.mouse.y < TextureHeight(upTexture);
00186 }
00187 pressed = hover && (event.mouse.button & OS_BUTTON_LEFT);
00188 motion = true;
00189 break;
00190
00191 case OS_KEYDOWN:
00192 if (wheel && motor)
00193 {
00194 float speed = world.GetMotorVelocity(motor);
00195 if (speed > 0 && event.key.key == OSK_LEFT)
00196 {
00197 world.SetMotorVelocity(motor, 0);
00198 freeze = true;
00199 }
00200 else if (speed < 0 && event.key.key == OSK_RIGHT)
00201 {
00202 world.SetMotorVelocity(motor, 0);
00203 freeze = true;
00204 }
00205 }
00206 break;
00207
00208 case OS_KEYUP:
00209 switch (event.key.key)
00210 {
00211 case 'x': case 'X': case 'q': case 'Q':
00212 case OSK_ESCAPE: exit(0); break;
00213 case OSK_LEFT: case OSK_RIGHT: freeze = false; break;
00214 }
00215 break;
00216 }
00217 }
00218
00219
00220 void ComplexApp::ProcessKeyState()
00221 {
00222 if (osIsKeyDown(OSK_SHIFT))
00223 {
00224 const float d = 1;
00225 if (osIsKeyDown(OSK_LEFT)) scrolloffset.x -= d;
00226 else if (osIsKeyDown(OSK_RIGHT)) scrolloffset.x += d;
00227 else if (osIsKeyDown(OSK_UP)) scrolloffset.y -= d;
00228 else if (osIsKeyDown(OSK_DOWN)) scrolloffset.y += d;
00229 }
00230 else
00231 {
00232 scrolloffset = vec2(0, 0);
00233 }
00234
00235 if (wheel && motor && !freeze && scrolloffset.x == 0 && scrolloffset.y == 0)
00236 {
00237 const float speed = world.GetMotorVelocity(motor);
00238 const float delta = 0.001f;
00239 const float max = 0.1f;
00240
00241 if (osIsKeyDown(OSK_LEFT) && speed > -max)
00242 world.SetMotorVelocity(motor, speed - delta);
00243 else if (osIsKeyDown(OSK_RIGHT) && speed < max)
00244 world.SetMotorVelocity(motor, speed + delta);
00245 }
00246
00247 if (wheel)
00248 {
00249 vec2 target = wheel->GetFlatlandObject()->GetGeometry().Center() - vec2(width / 2.0f, height * 0.75f);
00250 target += scrolloffset;
00251
00252 if (target.x < scrollbox.left) target.x = scrollbox.left;
00253 if (target.x + width > scrollbox.right) target.x = scrollbox.right - width;
00254 if (target.y < scrollbox.top) target.y = scrollbox.top;
00255 if (target.y + height > scrollbox.bottom) target.y = scrollbox.bottom - height;
00256
00257 SetTarget(target);
00258 }
00259 }
00260
00261 void SetPastel(Object *object)
00262 {
00263 float hue = 60;
00264 Color c(hue + (rand() % 90) - 45);
00265 object->Property().outlineColor = c;
00266 c.IncreaseBrightness(0.5);
00267 c.a = 0.9f;
00268 object->Property().fillColor = c;
00269 }
00270
00271 void ComplexApp::Draw() const
00272 {
00273 Clear();
00274 DrawScene();
00275 Blit(helpTexture, 500-128, 300-128);
00276 Blit(boostTexture, 1000, 3425);
00277
00278 glLoadIdentity();
00279 if (osShowCursor(OS_QUERY))
00280 Blit(pressed ? downTexture : upTexture, 2, 0, Color(1,1,1,hover ? 1 : 0.25f));
00281 }
00282
00283
00284 void ComplexApp::InitGl()
00285 {
00286 App::InitGl();
00287
00288 helpTexture = LoadTexture("keys.rgba");
00289 downTexture = LoadTexture("down.rgba");
00290 upTexture = LoadTexture("up.rgba");
00291 boostTexture = LoadTexture("boost.rgba");
00292 wheelTexture = LoadTexture("wheel.rgba");
00293 }
00294
00295
00296 void ComplexApp::InitWin()
00297 {
00298 osInit(InitialWidth, InitialHeight, fullscreen ? OS_FULLSCREEN : OS_RESIZABLE, 0);
00299 }
00300
00301
00302 void ComplexApp::boostCallback(ContactList &contacts)
00303 {
00304 if (contacts.Other() != app.wheel->GetFlatlandObject())
00305 return;
00306
00307 if (app.world.GetMotorVelocity(app.motor) < 0)
00308 app.world.SetMotorVelocity(app.motor, -0.4f);
00309 if (app.world.GetMotorVelocity(app.motor) > 0)
00310 app.world.SetMotorVelocity(app.motor, 0.4f);
00311 }
00312
00313
00314 void ComplexApp::pendulumCallback(ContactList &contacts)
00315 {
00316 if (contacts.Other() != app.wheel->GetFlatlandObject() || !app.pendulumAnchor)
00317 return;
00318
00319 app.world.DeleteJoint(app.pendulumAnchor);
00320 app.pendulumAnchor = 0;
00321 }
00322
00323
00324 void ComplexApp::bubbleCallback(ContactList &contacts)
00325 {
00326 if (contacts.Other() != app.wheel->GetFlatlandObject() || !app.bubbleAnchor)
00327 return;
00328
00329 app.world.DeleteJoint(app.bubbleAnchor);
00330 app.bubbleAnchor = 0;
00331
00332 Flatland::Object &front = *app.wheel->GetFlatlandObject();
00333 Flatland::Object &back = *app.wheel2->GetFlatlandObject();
00334 front.Move();
00335 back.Move();
00336 vec2 start = front.GetGeometry().Center();
00337 vec2 end = back.GetGeometry().Center();
00338 Beam *beam = new Beam(start, end, 2);
00339 beam->GetFlatlandObject()->Property().collisionMask = 0;
00340 beam->GetFlatlandObject()->SetMass(0.01f);
00341 beam->Property().outlineThickness = 0;
00342 beam->Property().fillColor = Color(0.25f, 0.35f, 0.6f, 1);
00343 beam->InsertFront(app.space);
00344
00345 app.world.Anchor(*beam->GetFlatlandObject(), front, start, 0, 0.01f);
00346 app.world.Anchor(*beam->GetFlatlandObject(), back, end, 0, 0.01f);
00347 }
00348
00349
00350 void ComplexApp::feederCallback(ContactList &contacts)
00351 {
00352 if (contacts.Other() != app.wheel->GetFlatlandObject() && contacts.Other() != app.wheel2->GetFlatlandObject())
00353 return;
00354
00355 app.world.SetMotorVelocity(app.blockFeeder, 0.035f);
00356 app.world.SetMotorVelocity(app.squareWheelMotor, -0.01f);
00357 }
00358
00359
00360 ComplexApp::ComplexApp(bool full) : fullscreen(full), App(GetWidth(full), GetHeight(full))
00361 {
00362 hover = false;
00363 freeze = false;
00364 pressed = false;
00365 wheel = 0;
00366 scrollbox = aabb(-250, -100, 5000, 5000);
00367 scrolloffset = vec2(0, 0);
00368
00369 InitWin();
00370 InitGl();
00371 InitOde();
00372
00373 Flatland::Object::Default().friction = 40;
00374 Demo::Object::Default().outlineThickness = 1;
00375
00376
00377 float radius = 27;
00378 wheel = new Wheel(vec2(400, 475), radius);
00379 wheel->SetTexture(wheelTexture);
00380 wheel->GetFlatlandObject()->Property().frictionMask = 15;
00381 wheel->GetFlatlandObject()->Property().collisionMask = ~7;
00382 wheel->Insert(space);
00383 motor = world.AddMotor(*wheel->GetFlatlandObject());
00384
00385
00386 float carLength = radius * 2.5f;
00387 vec2 center(3500, 890 - carLength);
00388 wheel2 = new Wheel(center, radius);
00389 wheel2->GetFlatlandObject()->SetMass(0.01f);
00390 wheel2->GetFlatlandObject()->Property().frictionMask = 7;
00391 wheel2->GetFlatlandObject()->Property().collisionMask = ~7;
00392 wheel2->SetTexture(wheelTexture);
00393 wheel2->Insert(space);
00394 Ball *bubble = new Ball(center, carLength);
00395 bubble->Property().outlineThickness = 3;
00396 bubble->Property().fillColor = Color(1,0,0,0.1f);
00397 bubble->GetFlatlandObject()->Property().collisionMask = 4;
00398 bubble->GetFlatlandObject()->Property().friction = dInfinity;
00399 bubble->GetFlatlandObject()->Property().callback = bubbleCallback;
00400 bubble->Insert(space);
00401 bubbleAnchor = Glue(bubble, wheel2);
00402
00403
00404 Demo::Object::Default().outlineColor = Color::White;
00405 Demo::Object::Default().fillColor = Color(106/255.0f, 160/255.0f, 248/255.0f, 1);
00406 Demo::Object::Default().altFillColor = Color::White;
00407
00408
00409 Terrain *t = new Terrain(vec2(-250, 400), -100);
00410 for (float theta = 175; theta >= 0; theta -= 5)
00411 t->Add(vec2(50, 400) + vec2(300, 0).rotate(theta));
00412 t->Add(vec2(1000, 400));
00413 for (float theta = 230; theta <= 270; theta += 10)
00414 t->Add(vec2(1500, 750) + vec2(50, 0).rotate(theta));
00415 t->Add(vec2(2000, 800));
00416 for (float theta = 270; theta < 320; theta += 10)
00417 t->Add(vec2(2018, 750) + vec2(50, 0).rotate(theta));
00418 t->Add(vec2(2500, 400));
00419 t->Add(vec2(4100, 400));
00420 t->GetFlatlandObject()->Property().friction = dInfinity;
00421 t->Insert(space);
00422
00423
00424 t = new Terrain(vec2(0, 590), 1100);
00425 t->Add(vec2(950, 590));
00426 for (float theta = 80; theta >= 0; theta -= 10)
00427 t->Add(vec2(950, 640) + vec2(50, 0).rotate(theta));
00428 t->Insert(space);
00429 t->InsertEastBorder(space);
00430 space << new Line(vec2(1000, 900), vec2(1000, 3000));
00431
00432 t = new Terrain(vec2(1000, 890), 1100);
00433 t->Add(vec2(1500, 890));
00434 t->Insert(space);
00435
00436 t = new Terrain(vec2(2000, 890), 1100);
00437 t->Add(vec2(4000, 890));
00438 t->Insert(space);
00439 t->GetFlatlandObject()->Property().collisionMask = ~3;
00440
00441
00442 {
00443 Flatland::Object::PushProperties();
00444 Flatland::Object::Default().frictionMask = 7;
00445 vec2 start = vec2(1500, 890);
00446 vec2 end = vec2(2000, 890);
00447 float slack = 40;
00448 float length = end.x - start.x + slack;
00449 float tautness = 20000;
00450 float bottom = 1100;
00451 Rope *r = new Rope(start, end, length, tautness);
00452 r->Terrainify(bottom);
00453 r->Insert(space);
00454 Anchor(r->front(), start);
00455 Anchor(r->back(), end);
00456 Flatland::Object::PopProperties();
00457 }
00458
00459
00460 {
00461 Flatland::Object::PushProperties();
00462 Object::PushProperties();
00463
00464 Flatland::Object::Default().collisionMask = 3;
00465 Object::Default().fillColor = Color(0,0,0,1);
00466 Object::Default().outlineColor = Color(0.5f,0.7f,1,1);
00467 Object::Default().outlineThickness = 4;
00468
00469 vec2 start = vec2(2720, 700);
00470 vec2 end = vec2(2670, 820);
00471 float thickness = 5;
00472 Beam *tether = new Beam(start, end, thickness);
00473 tether->Insert(space);
00474
00475 float radius = 20;
00476 end = end + (end - start).hat() * radius;
00477 Flatland::Circle *cannonball = new Flatland::Circle(end, radius);
00478 tether->Add(cannonball);
00479
00480 tether->GetFlatlandObject()->Property().callback = pendulumCallback;
00481 tether->GetFlatlandObject()->SetMass(100);
00482 tether->GetFlatlandObject()->Property().frictionMask = 0;
00483
00484 Anchor(tether, start);
00485 pendulumAnchor = Anchor(tether, end);
00486
00487 Flatland::Object::PopProperties();
00488 Object::PopProperties();
00489 }
00490
00491
00492 for (int i = 0; i < 20; ++i)
00493 {
00494 Block *block = new Block(vec2(2750 + i * 30.0f, 890 - 15), 10, 30);
00495 Color c(60.0f + (rand() % 90) - 45);
00496 block->Property().outlineColor = c;
00497 c.IncreaseBrightness(0.5);
00498 c.a = 0.9f;
00499 block->Property().fillColor = c;
00500 block->GetFlatlandObject()->SetMass(40);
00501 block->GetFlatlandObject()->Property().frictionMask = 1 + i % 2;
00502 block->Insert(space);
00503 }
00504
00505
00506 {
00507 vec2 center(1150, 750);
00508 float width = 200;
00509 float height = 5;
00510 vec2 hinge(center.x - width / 4, center.y);
00511 Catapult *c = new Catapult(center, width, height, hinge);
00512 c->Rotate(-22);
00513 c->Insert(space);
00514 c->InsertSouthEastAnchor(space);
00515
00516 center += vec2(90, -50);
00517 Block *b = new Block(center, 10, 10);
00518 b->GetFlatlandObject()->SetMass(0.5);
00519 b->GetFlatlandObject()->Property().friction = dInfinity;
00520 b->Property().fillColor = Color::PaleYellow;
00521 b->Property().outlineColor = Color::PaleYellow;
00522 b->Insert(space);
00523
00524 center.x -= 14;
00525 b = new Block(center, 10, 10);
00526 b->GetFlatlandObject()->SetMass(0.5);
00527 b->GetFlatlandObject()->Property().friction = dInfinity;
00528 b->Property().fillColor = Color::PaleYellow;
00529 b->Property().outlineColor = Color::PaleYellow;
00530 b->Insert(space);
00531 }
00532
00533
00534 {
00535 Flatland::Object::PushProperties();
00536 Flatland::Object::Default().frictionMask = 1;
00537 Flatland::Object::Default().friction = 1;
00538 Flatland::Object::Default().density = 0.1f;
00539 float width = 90;
00540 float height = 50;
00541 Block *buffer1 = new Block(vec2(4050, 1300), width, height);
00542 SetPastel(buffer1);
00543 buffer1->Insert(space);
00544 Block *buffer2 = new Block(vec2(4050, 1000), width, height);
00545 SetPastel(buffer2);
00546 buffer2->Insert(space);
00547 Flatland::Object::PopProperties();
00548
00549 buffer2->GetFlatlandObject()->Property().callback = feederCallback;
00550
00551 Line *l = new Line(vec2(4000, 890), vec2(4000, 1620));
00552 l->GetFlatlandObject()->Property().frictionMask = 2;
00553 l->Insert(space);
00554 }
00555
00556
00557 t = 0;
00558 float dx = 5;
00559 float asinh1 = .881373587019543f;
00560 float xx = -asinh1;
00561 for (float x = 3000 + dx; x <= 4000; x += dx)
00562 {
00563 float y = 1570 + 50 * cosh(xx);
00564 if (!t)
00565 t = new Terrain(vec2(0, y), 1100);
00566 else
00567 t->Add(vec2(x, y));
00568 xx += 2 * asinh1 / 15;
00569 if (xx > asinh1)
00570 xx = -asinh1;
00571 }
00572 t->Insert(space);
00573
00574 Block *b = new Block(vec2(3923, 1500), 92, 92);
00575 b->Property().fillColor = Color::Black;
00576 b->Insert(space);
00577 b->GetFlatlandObject()->Property().friction = dInfinity;
00578 squareWheelMotor = world.AddMotor(*b->GetFlatlandObject());
00579
00580
00581 t = new Terrain(vec2(0, 590 - 100), 595, true, false);
00582 t->Add(vec2(20, 590 - 100));
00583 t->Property().altFillColor = t->Property().fillColor;
00584 t->Insert(space);
00585
00586 t = new Terrain(vec2(1500, 2850), 2850);
00587 for (float x = 1510; x <= 4100; x += 10)
00588 {
00589 float y = 2500 - log10f((x - 1400) / 270) * 800;
00590 t->Add(vec2(x, y));
00591 }
00592 t->Insert(space);
00593
00594 space << new Line(vec2(1000, 3000), vec2(1750, 3000));
00595 space << new Line(vec2(2500, 3000), vec2(3000, 3000));
00596
00597
00598 {
00599 Flatland::Object::PushProperties();
00600 Flatland::Object::Default().friction = dInfinity;
00601 Flatland::Object::Default().frictionMask = 7;
00602 Flatland::Object::Default().density = 5;
00603 vec2 start = vec2(1750, 3000);
00604 vec2 end = vec2(2500, 3000);
00605 float slack = 40;
00606 float length = end.x - start.x + slack;
00607 float tautness = 20000;
00608 Rope *r = new Rope(start, end, length, tautness);
00609 r->Property().outlineColor = Color::Red;
00610 r->Property().outlineThickness = 3;
00611 r->Insert(space);
00612 Anchor(r->front(), start);
00613 Anchor(r->back(), end);
00614 Flatland::Object::PopProperties();
00615 }
00616
00617
00618 t = new Terrain(vec2(-250, 400), 5000);
00619 for (float x = 0.5f + 0.1f; x < 10; x += 0.1f)
00620 {
00621 float y = 5 / x;
00622 vec2 v;
00623 v.y = (y - 0.5f) / 9.5f;
00624 v.y = 1 - v.y;
00625 v.y = v.y * (3500 - 400) + 400;
00626 v.x = (x - 0.5f) / 9.5f;
00627 v.x = v.x * (1000 - -250) + -250;
00628 t->Add(v);
00629 }
00630 t->Add(vec2(1000, 3500));
00631 float dtheta = pi / 50;
00632 for (float theta = dtheta; theta < pi; theta += dtheta)
00633 t->Add(vec2(1000 + theta * 1500 / pi, 4000 + 500 * cosf(pi - theta)));
00634 t->Add(vec2(2500, 4500));
00635 t->Add(vec2(4050, 4500));
00636 for (float theta = -90 + 10; theta < 0; theta += 10)
00637 t->Add(vec2(4075, 4475) + vec2(25, 0).rotate(theta));
00638 t->Add(vec2(4100, -100));
00639 t->Add(vec2(5000, -100));
00640 t->GetFlatlandObject()->Property().friction = dInfinity;
00641 t->GetFlatlandObject()->Property().collisionMask = ~8;
00642 t->GetFlatlandObject()->Property().frictionMask = 4;
00643 t->Insert(space);
00644
00645
00646 Point *boost = new Point(vec2(1000 + 32, 3425 + 32));
00647 boost->GetFlatlandObject()->Property().callback = boostCallback;
00648 boost->GetFlatlandObject()->Property().collisionMask = 0;
00649 boost->Insert(space);
00650 Anchor(boost, vec2(1000 + 32, 3425 + 32));
00651
00652
00653 {
00654 Object::PushProperties();
00655 Object::Default().fillColor = Color::PaleRed;
00656 Object::Default().outlineColor = Color::Black;
00657 Object::Default().outlineThickness = 2;
00658
00659 vec2 start(4300, 1670);
00660 vec2 end(4600, 1500);
00661 float length = 130;
00662
00663 start -= vec2(170, 0);
00664 end -= vec2(170, 0);
00665
00666
00667 Wheel *w = new Wheel(end, 100);
00668 w->Insert(space);
00669 w->GetFlatlandObject()->Property().collisionMask = 0;
00670 Anchor(w, w->GetFlatlandObject()->GetGeometry().Center());
00671 blockFeeder = world.AddMotor(*w->GetFlatlandObject());
00672
00673 Object::Default().outlineThickness = 4;
00674
00675
00676 Beam *pusher = new Beam(start - vec2(length, 0), start, 50);
00677 pusher->GetFlatlandObject()->Property().collisionMask = 8;
00678 pusher->Insert(space);
00679 AnchorAxis(pusher, vec2(1, 0));
00680
00681
00682 end -= vec2(60, 0);
00683 Beam *transmission = new Beam(start, end, 20);
00684 transmission->Insert(space);
00685 transmission->GetFlatlandObject()->Property().collisionMask = 0;
00686 Anchor(transmission, w, end);
00687 Anchor(transmission, pusher, start);
00688
00689 Object::PopProperties();
00690 }
00691 }