main.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. function DeathBallToy::create( %this )
  23. {
  24. // Execute behavior scripts
  25. exec("./scripts/dealsDamageBehavior.cs");
  26. exec("./scripts/takesDamageBehavior.cs");
  27. exec("./scripts/faceObjectBehavior.cs");
  28. exec("./scripts/moveTowardBehavior.cs");
  29. exec("./scripts/spawnAreaBehavior.cs");
  30. // Initialize the toys settings.
  31. DeathBallToy.WorldTop = 35;
  32. DeathBallToy.WorldBottom = -110;
  33. DeathBallToy.WorldLeft = -50;
  34. DeathBallToy.WorldRight = 140;
  35. DeathBallToy.rotateSpeed = 360;
  36. DeathBallToy.maxBallSpeed = 10;
  37. DeathBallToy.ballSpeed = 5;
  38. DeathBallToy.soldierSpeed = 1;
  39. DeathBallToy.maxSoldierSpeed = 10;
  40. DeathballToy.spawnAmount = 80;
  41. // Add the custom controls.
  42. addNumericOption("Deathball move speed", 1, 10, 1, "setBallSpeed", DeathBallToy.ballSpeed, false, "Sets the deathball movement speed.");
  43. addNumericOption("Soldier count", 40, 100, 10, "setSpawnAmount", DeathBallToy.spawnAmount, true, "Sets the solider count.");
  44. addNumericOption("Soldier speed", 1, 10, 1, "setSoldierSpeed", DeathBallToy.soldierSpeed, false, "Sets the soldier speed.");
  45. // Create the BehaviorTemplate definitions. They are automatically added to the
  46. // DeathBallToy scopeset in the "create" functions
  47. %this.createDealsDamageBehavior();
  48. %this.createTakesDamageBehavior();
  49. %this.createFaceObjectBehavior();
  50. %this.createMoveTowardBehavior();
  51. %this.createSpawnAreaBehavior();
  52. // Reset the toy initially.
  53. DeathBallToy.reset();
  54. }
  55. //-----------------------------------------------------------------------------
  56. function DeathBallToy::destroy( %this )
  57. {
  58. // Cancel any pending events.
  59. DeathBallToy::cancelPendingEvents();
  60. }
  61. //-----------------------------------------------------------------------------
  62. function DeathBallToy::reset(%this)
  63. {
  64. // Clear the scene.
  65. SandboxScene.clear();
  66. // Set the gravity.
  67. SandboxScene.setGravity(0, 0);
  68. // Limit the camera to the four sections of the desert
  69. SandboxWindow.setViewLimitOn( DeathBallToy.WorldLeft, DeathBallToy.WorldBottom, DeathBallToy.WorldRight, DeathBallToy.WorldTop );
  70. // Add backgrounds
  71. %this.createDesertBackgrounds();
  72. // Create invisible walls for the deathball to bounce off
  73. %this.createBarriers();
  74. // Add deathball
  75. %this.spawnDeathball("50 -40");
  76. // Create the soldier enemy we will be spawning
  77. %this.generateSoldierTemplate();
  78. // Setup the spawners
  79. %this.setupSpawnPoints();
  80. }
  81. //-----------------------------------------------------------------------------
  82. function DeathBallToy::createDesertBackgrounds(%this)
  83. {
  84. // Create the composite sprite.
  85. %composite = new CompositeSprite();
  86. %composite.setSceneLayer(3);
  87. // Set the batch layout mode. We must do this before we add any sprites.
  88. %composite.SetBatchLayout( "off" );
  89. // Add upper left desert
  90. %composite.addSprite();
  91. %composite.setSpriteLocalPosition(0, 0);
  92. %composite.setSpriteSize(100, 75);
  93. %composite.setSpriteImage( "DeathBallToy:upperLeftDesert");
  94. // Add upper right desert
  95. %composite.addSprite();
  96. %composite.setSpriteLocalPosition(100, 0);
  97. %composite.setSpriteSize(100, 75);
  98. %composite.setSpriteImage( "DeathBallToy:upperRightDesert");
  99. // Add lower left desert
  100. %composite.addSprite();
  101. %composite.setSpriteLocalPosition(0, -75);
  102. %composite.setSpriteSize(100, 75);
  103. %composite.setSpriteImage( "DeathBallToy:lowerLeftDesert");
  104. // Add lower right desert
  105. %composite.addSprite();
  106. %composite.setSpriteLocalPosition(100, -75);
  107. %composite.setSpriteSize(100, 75);
  108. %composite.setSpriteImage( "DeathBallToy:lowerRightDesert");
  109. // Add to the scene.
  110. SandboxScene.add( %composite );
  111. }
  112. function DeathBallToy::createBarriers(%this)
  113. {
  114. %leftWall = new SceneObject()
  115. {
  116. Size = "10 500";
  117. Position = "-55 0";
  118. };
  119. %leftWall.createPolygonBoxCollisionShape( 10, 500);
  120. %leftWall.setBodyType( "static" );
  121. %rightWall = new SceneObject()
  122. {
  123. Size = "10 500";
  124. Position = "155 0";
  125. };
  126. %rightWall.createPolygonBoxCollisionShape( 10, 500);
  127. %rightWall.setBodyType( "static" );
  128. %topWall = new SceneObject()
  129. {
  130. Size = "500 10";
  131. Position = "0 42";
  132. };
  133. %topWall.createPolygonBoxCollisionShape( 500, 10);
  134. %topWall.setBodyType( "static" );
  135. %bottomWall = new SceneObject()
  136. {
  137. Size = "500 10";
  138. Position = "0 -118";
  139. };
  140. %bottomWall.createPolygonBoxCollisionShape( 500, 10);
  141. %bottomWall.setBodyType( "static" );
  142. SandboxScene.add(%leftWall);
  143. SandboxScene.add(%rightWall);
  144. SandboxScene.add(%topWall);
  145. SandboxScene.add(%bottomWall);
  146. }
  147. //-----------------------------------------------------------------------------
  148. function DeathBallToy::spawnDeathball(%this, %position)
  149. {
  150. %db = new Sprite(Deathball)
  151. {
  152. Animation = "DeathBallToy:dbForwardAnim";
  153. position = %position;
  154. size = "20 20";
  155. SceneLayer = "1";
  156. SceneGroup = "14";
  157. minSpeed = "5";
  158. maxSpeed = "15";
  159. CollisionCallback = true;
  160. };
  161. %db.createCircleCollisionShape(8);
  162. %dealsDamageBehavior = DealsDamageBehavior.createInstance();
  163. %dealsDamageBehavior.initialize(100, false);
  164. Deathball.addBehavior(%dealsDamageBehavior);
  165. //%db.pauseAnimation(1);
  166. Deathball.rollSchedule = Deathball.schedule(100, "updateRollAnimation");
  167. SandboxScene.add(%db);
  168. SandboxWindow.mount( Deathball, "0 0", 0, true, false );
  169. }
  170. //-----------------------------------------------------------------------------
  171. function Deathball::updateRollAnimation(%this)
  172. {
  173. %this.rollSchedule = "";
  174. %velocity = %this.getLinearVelocity();
  175. %scaledVelocity = VectorLen(%velocity); // (mAbs(getWord(%velocity, 0))) + mAbs(getWord(%velocity, 1)) / 50;
  176. %flooredVelocity = mFloatLength(%scaledVelocity, 1);
  177. %this.setAnimationTimeScale(%flooredVelocity / 20);
  178. %this.rollSchedule = %this.schedule(100, updateRollAnimation);
  179. }
  180. //-----------------------------------------------------------------------------
  181. function DeathBallToy::generateSoldierTemplate(%this)
  182. {
  183. // Create the soldier sprite
  184. %soldier = new Sprite()
  185. {
  186. Animation = "DeathBallToy:soldierAnim";
  187. size = "10 10";
  188. SceneLayer = "2";
  189. SceneGroup = "14";
  190. CollisionCallback = true;
  191. Class = "DeathBallSoldier";
  192. };
  193. %soldier.createPolygonBoxCollisionShape(5, 8);
  194. // Return it to the toy
  195. %this.soldierTemplate = %soldier;
  196. SandboxScene.add(%this.soldierTemplate);
  197. // Disable it
  198. %this.soldierTemplate.setEnabled(0);
  199. // Add the behaviors
  200. %takesDamageBehavior = TakesDamageBehavior.createInstance();
  201. %takesDamageBehavior.initialize(1, "", "", "DeathBallToy:soldierDeathAnim", false);
  202. %moveTowardBehavior = MoveTowardBehavior.createInstance();
  203. %adjustedSpeed = DeathBallToy.soldierSpeed / DeathBallToy.maxSoldierSpeed;
  204. %moveTowardBehavior.initialize(Deathball, %adjustedSpeed);
  205. %faceObjectBehavior = FaceObjectBehavior.createInstance();
  206. %faceObjectBehavior.initialize(Deathball, 0, 0);
  207. %soldier.addBehavior(%takesDamageBehavior);
  208. %soldier.addBehavior(%moveTowardBehavior);
  209. %soldier.addBehavior(%faceObjectBehavior);
  210. }
  211. //-----------------------------------------------------------------------------
  212. function DeathBallToy::setupSpawnPoints(%this)
  213. {
  214. %amount = %this.spawnAmount / 6;
  215. // Creating four in the corners of the desert
  216. %this.createSpawnPoint("-30 10", %amount);
  217. %this.createSpawnPoint("50 10", %amount);
  218. %this.createSpawnPoint("120 10", %amount);
  219. %this.createSpawnPoint("-30 -90", %amount);
  220. %this.createSpawnPoint("50 -90", %amount);
  221. %this.createSpawnPoint("120 -90", %amount);
  222. }
  223. //-----------------------------------------------------------------------------
  224. function DeathBallToy::createSpawnPoint(%this, %position, %amount)
  225. {
  226. %spawnPoint = new sceneObject()
  227. {
  228. size = "40 40";
  229. position = %position;
  230. };
  231. %spawnPointBehavior = %this.spawnAreaBehavior.createInstance();
  232. %spawnPointBehavior.initialize(%this.soldierTemplate, %amount, 0.5, 0, true, "Area");
  233. %spawnPoint.addBehavior(%spawnPointBehavior);
  234. SandboxScene.add(%spawnPoint);
  235. }
  236. //-----------------------------------------------------------------------------
  237. function DeathBallToy::createDealsDamageBehavior(%this)
  238. {
  239. // Create the named template and retain it as a custom field on this toy
  240. %this.dealsDamageBehavior = new BehaviorTemplate(DealsDamageBehavior);
  241. // Fill in the details of the behavior
  242. %this.dealsDamageBehavior.friendlyName = "Deals Damage";
  243. %this.dealsDamageBehavior.behaviorType = "Game";
  244. %this.dealsDamageBehavior.description = "Set the object to deal damage to TakesDamage objects it collides with";
  245. // Add the custom behavior fields
  246. %this.dealsDamageBehavior.addBehaviorField(strength, "The amount of damage the object deals", int, 10);
  247. %this.dealsDamageBehavior.addBehaviorField(deleteOnHit, "Delete the object when it collides", bool, 1);
  248. // Add the BehaviorTemplate to the scope set so it is destroyed when the module is unloaded
  249. DeathBallToy.add(%this.dealsDamageBehavior);
  250. }
  251. //-----------------------------------------------------------------------------
  252. function DeathBallToy::createTakesDamageBehavior(%this)
  253. {
  254. // Create the named template and retain it as a custom field on this toy
  255. %this.takesDamageBehavior = new BehaviorTemplate(TakesDamageBehavior);
  256. // Fill in the details of the behavior
  257. %this.takesDamageBehavior.friendlyName = "Takes Damage";
  258. %this.takesDamageBehavior.behaviorType = "Game";
  259. %this.takesDamageBehavior.description = "Set the object to take damage from DealsDamage objects that collide with it";
  260. // Add the custom behavior fields
  261. %this.takesDamageBehavior.addBehaviorField(health, "The amount of health the object has", int, 100);
  262. %this.takesDamageBehavior.addBehaviorField(explodeEffect, "The particle effect to play on death", asset, "", ParticleAsset);
  263. %this.takesDamageBehavior.addBehaviorField(spawnEffect, "The particle effect to play on spawn", asset, "", ParticleAsset);
  264. %this.takesDamageBehavior.addBehaviorField(deathAnim, "The object's death animation, alternative to explodeEffect", asset, "", AnimationAsset);
  265. %this.takesDamageBehavior.addBehaviorField(deleteOnDeath, "Delete the owner upon dieing", bool, false);
  266. // Add the BehaviorTemplate to the scope set so it is destroyed when the module is unloaded
  267. DeathBallToy.add(%this.takesDamageBehavior);
  268. }
  269. //-----------------------------------------------------------------------------
  270. function DeathBallToy::createFaceObjectBehavior(%this)
  271. {
  272. // Create the named template and retain it as a custom field on this toy
  273. %this.faceObjectBehavior = new BehaviorTemplate(FaceObjectBehavior);
  274. // Fill in the details of the behavior
  275. %this.faceObjectBehavior.friendlyName = "Face Object";
  276. %this.faceObjectBehavior.behaviorType = "AI";
  277. %this.faceObjectBehavior.description = "Set the object to face another object";
  278. // Add the custom behavior fields
  279. %this.faceObjectBehavior.addBehaviorField(target, "The object to face", object, "", sceneObject);
  280. %this.faceObjectBehavior.addBehaviorField(turnSpeed, "The speed to rotate at (degrees per second). Use 0 to snap", float, 0.0);
  281. %this.faceObjectBehavior.addBehaviorField(rotationOffset, "The rotation offset (degrees)", float, 0.0);
  282. // Add the BehaviorTemplate to the scope set so it is destroyed when the module is unloaded
  283. DeathBallToy.add(%this.faceObjectBehavior);
  284. }
  285. //-----------------------------------------------------------------------------
  286. function DeathBallToy::createMoveTowardBehavior(%this)
  287. {
  288. // Create the named template and retain it as a custom field on this toy
  289. %this.moveTowardBehavior = new BehaviorTemplate(MoveTowardBehavior);
  290. // Fill in the details of the behavior
  291. %this.moveTowardBehavior.friendlyName = "Move Toward";
  292. %this.moveTowardBehavior.behaviorType = "AI";
  293. %this.moveTowardBehavior.description = "Set the object to move toward another object";
  294. // Add the custom behavior fields
  295. %this.moveTowardBehavior.addBehaviorField(target, "The object to move toward", object, "", sceneObject);
  296. %this.moveTowardBehavior.addBehaviorField(speed, "The speed to move toward the object at (world units per second)", float, 2.0);
  297. // Add the BehaviorTemplate to the scope set so it is destroyed when the module is unloaded
  298. DeathBallToy.add(%this.moveTowardBehavior);
  299. }
  300. //-----------------------------------------------------------------------------
  301. function DeathBallToy::createSpawnAreaBehavior(%this)
  302. {
  303. // Create the named template and retain it as a custom field on this toy
  304. %this.spawnAreaBehavior = new BehaviorTemplate(SpawnAreaBehavior);
  305. // Fill in the details of the behavior
  306. %this.spawnAreaBehavior.friendlyName = "Spawn Area";
  307. %this.spawnAreaBehavior.behaviorType = "AI";
  308. %this.spawnAreaBehavior.description = "Spawns objects inside the area of this object";
  309. // Add the custom behavior fields
  310. %this.spawnAreaBehavior.addBehaviorField(object, "The object to clone", object, "", sceneObject);
  311. %this.spawnAreaBehavior.addBehaviorField(count, "The number of objects to clone (-1 for infinite)", int, 50);
  312. %this.spawnAreaBehavior.addBehaviorField(spawnTime, "The time between spawns (seconds)", float, 2.0);
  313. %this.spawnAreaBehavior.addBehaviorField(spawnVariance, "The variance in the spawn time (seconds)", float, 1.0);
  314. %this.spawnAreaBehavior.addBehaviorField(autoSpawn, "Automatically start/stop spawning", bool, true);
  315. %spawnLocations = "Area" TAB "Edges" TAB "Center" TAB "Top" TAB "Bottom" TAB "Left" TAB "Right";
  316. %this.spawnAreaBehavior.addBehaviorField(spawnLocation, "The are in which objects can be spawned", enum, "Area", %spawnLocations);
  317. // Add the BehaviorTemplate to the scope set so it is destroyed when the module is unloaded
  318. DeathBallToy.add(%this.spawnAreaBehavior);
  319. }
  320. //-----------------------------------------------------------------------------
  321. function DeathBallToy::setBallSpeed(%this, %value)
  322. {
  323. %this.ballSpeed = %value;
  324. }
  325. //-----------------------------------------------------------------------------
  326. function DeathBallToy::setSpawnAmount(%this, %value)
  327. {
  328. %this.spawnAmount = %value;
  329. }
  330. //-----------------------------------------------------------------------------
  331. function DeathBallToy::setSoldierSpeed(%this, %value)
  332. {
  333. %this.soldierSpeed = %value;
  334. }
  335. //-----------------------------------------------------------------------------
  336. function DeathBallToy::cancelPendingEvents()
  337. {
  338. // Finish if there are not pending events.
  339. if ( !isEventPending(DeathBall.rollSchedule) )
  340. return;
  341. cancel(DeathBall.rollSchedule);
  342. DeathBall.rollSchedule = "";
  343. }
  344. //-----------------------------------------------------------------------------
  345. function DeathBallToy::onTouchDown(%this, %touchID, %worldPosition)
  346. {
  347. %origin = Deathball.getPosition();
  348. %angle = mAtan( Vector2Sub( %worldPosition, %origin ) ) - 90;
  349. Deathball.RotateTo( %angle, DeathBallToy.rotateSpeed );
  350. %adjustedSpeed = DeathBallToy.ballSpeed / DeathBallToy.maxBallSpeed;
  351. %relativePosition = VectorSub(%worldPosition, Deathball.getPosition());
  352. %scaledVelocity = VectorScale(%relativePosition, %adjustedSpeed);
  353. Deathball.setLinearVelocity( getWord(%scaledVelocity, 0), getWord(%scaledVelocity, 1) );
  354. }
  355. //-----------------------------------------------------------------------------
  356. function DeathBallToy::onTouchUp(%this, %touchID, %worldPosition)
  357. {
  358. %origin = Deathball.getPosition();
  359. %angle = mAtan( Vector2Sub( %worldPosition, %origin ) );
  360. // Since the speed is used instead of time, we can use the current velocity to set it's speed.
  361. %adjustedSpeed = VectorLen(DeathBall.getLinearVelocity());// (DeathBallToy.ballSpeed / DeathBallToy.maxBallSpeed) * 3000;
  362. Deathball.MoveTo( %worldPosition, %adjustedSpeed, true, false );
  363. }
  364. //-----------------------------------------------------------------------------
  365. function DeathBallToy::onTouchDragged(%this, %touchID, %worldPosition)
  366. {
  367. %origin = Deathball.getPosition();
  368. %angle = mAtan( Vector2Sub( %worldPosition, %origin ) ) - 90;
  369. Deathball.RotateTo( %angle, DeathBallToy.rotateSpeed );
  370. %adjustedSpeed = DeathBallToy.ballSpeed / DeathBallToy.maxBallSpeed;
  371. %relativePosition = VectorSub(%worldPosition, Deathball.getPosition());
  372. %scaledVelocity = VectorScale(%relativePosition, %adjustedSpeed);
  373. Deathball.setLinearVelocity( getWord(%scaledVelocity, 0), getWord(%scaledVelocity, 1) );
  374. }