Showing posts with label MOAI. Show all posts
Showing posts with label MOAI. Show all posts

Sunday, 17 May 2015

10 Games.

I've read that you should make 10 games before you reach success in game development.
This isn't a strict value I'm guessing or any kind of hard and fast rule. However, I do feel that it's in a game developer's best interests to make as many games as possible. Partly to hone one's coding skills but mostly to understand what makes a game interesting and fun. It's also an important journey of self discovery, to understand one's talents and limitations.

I wrote many games on the spectrum, however none of them were what I would call "Finished" apart from the game I've listed here. Unfortunately, nothing remains of any of them, it was over 20 years ago. The rest of the games were for the PC platform and more recently for mobile devices..

So here's my list.

Treasure Caves

 ZX Spectrum. A platform game where you collect treasure in a scrolling maze like level to activate an exit which would appear after you'd collected enough treasure, all while avoiding traps and using teleports to move you to the next platform above. Perilous spike pits would plague your every fall.
The game included an editor where I would challenge a friend with a cunning level and he'd return the favour with an even more cunning level. This game was memorable to me because of the large levels, the large sprites. I had to write a Run Length Encoding compression system in Z80 (before I knew what RLE was) to fit the levels into memory. The game was fast and allowed for very devious traps. Even though the gameplay was simple, it was a lot of fun.

  • Language: Z80 Assembler, Basic
  • Status: Completed, Lost


SUOF: Subtle Use of Force

A vertically scrolling shooter where you must defeat an invading alien force using a previously mothballed fighter. You could collect weapons dropped from dead enemies, it had a variety of different aliens, each with their own abilities and tricks. There were also Bosses to defeat who also had their own patterns and abilities.

  • Language: Borland C
  • OS: PC MSDos. 
  • Status: Completed - Unreleased


CHAOS: Battle of the Wizards - Remake.

A remake of the classic gameby Julian Gollop. Chaos pits 2 or more wizards against each-other in a last man standing battle to the death.
It was abandoned due to really difficult to track down issues in the code which would take a massive amount of work to fix. However the gameplay was faithful to the original with every spell and monster re-created.

  • Language: VB6
  • OS: Windows
  • Status: Incomplete - Abandoned


GUNS: A DelphiX example. 

A turn based projectile warfare tank game where you control a squad of flying tanks who must fire at the opponents flying tanks on opposing mountain sides across a valley. AI behaviour aimed the turrets of the enemy tanks and raised shields. Limited fuel reserves and accurate aiming of the AI opponent meant that battles were usually quick and devastating -often needing quick reflexes and tactical uses of the shield. The terrain was fully destructible and this was the first game I'd written with a floating camera which worked independently of the player's control. It moved to focus on the selected tank and would also follow projectiles through the air to see where they landed - allowing the player to adjust their aim. All in real time. The game was published as a demonstration of how to make games using the DelphiX component set.

  • Language: Object Pascal
  • Framework: DelphiX
  • OS: Windows
  • Status: Completed - Released for free




Anomalous

 A rip in space has occurred following an unexpected situation during a science experiment trying to find a new source of energy to save our world from environmental disaster. The device causing the rip has fallen through the rift, it's up to  you to retrieve it before the earth and the alien world perishes. An entire story arc was planned involving alien civilizations and a civil war which would complicate your efforts.
It was a 2D platformer with skeletal animation - built from the ground up using a home grown engine called the CBCFoundation. An entire toolchain was developed to work alongside the engine including a level editor, skeletal animation editor and animator.
Unfortunately, a hard disk failure meant that I'd lost the source files for the majority of the art assets. It was an event which the project never recovered from.

  • Language: Object Pascal.
  • Framework: CBCFoundation, SDL
  • OS: Windows, Linux
  • Status: Incomplete - Abandoned due to hardware failure.



Lander


A variant on the old Lunar Lander game with a twist. You're in charge of a rocket which has to pickup and ferry spacemen from one part of the moon to another. Instead of using retro thrusters to control your descent, you have your main rocket which you must rotate around to move and slow down. Landing on the pad was tricky, you had to land at just the right speed and at the correct angle or Kaboom, however you could take some damage by hitting the mountains - making a horrible metal scraping sound as the rocket takes a pounding. I just couldn't get this game working as well as I wanted. The framerate suffered due to software rendering and the engine did not allow for the level of fidelity in the terrain I wanted.
I would later rebuild this in Unity as an example, however it wasn't as good or as much fun as I'd hoped and was ditched.

  • Language: Object Pascal.
  • Framework: CBCFoundation, SDL
  • OS: Windows, Linux
  • Status: Incomplete - Abandoned


Anomalous

A 3D version of Anomalous written using the Torque engine. This game was going to be the version of Anomalous it was meant to be. The earlier version being abandoned following a horrific hard drive failure. I created a lot of art assets however it seemed that no matter how many assets I created, I always needed more and the better I got at creating 3D assets, the worse my earlier work looked in comparison and my animation was horrible. Compared to professional offerings, I couldn't seem to compete. I needed to rethink this game. However I had a story fleshed out - just like the original attempt. It was just too big for a single person to build.

  • Language: C++
  • Engine: Torque Engine
  • OS: Windows
  • Status: Incomplete - Abandoned


Tetris

An example of how to build a tetris game, built in a weekend and offered on-line as an example. It was fully functional and surprisingly addictive, which I suppose goes to show how close I was to the original. It is an exercise that every game developer should do.

  • Language: VB6
  • OS: Windows
  • Status: Complete - Released for free.




GUNS

A 3D version of GUNS written using the Torque engine. A fully 3D version of the original game complete with a story about aliens using the Earth as a kind of courtroom to settle petty disputes with squad based tank combat. The human race being powerless to stop them, but the aliens appear oblivious to their plight although seem to have no designs on taking over the world. Abandoned due to complexities with the Torque engine in making it do what was needed for this game and because 3D games need a lot of good art assets in order to look even nearly nice. It became obvious that alone I wouldn't be able to make this game no matter how much work I put into it.

  • Language: C++ and TorqueScript
  • Engine: Torque Engine.
  • OS: Windows
  • Status: Incomplete - Abandoned



GUNS:Reloaded.

A back to basics reboot of GUNS with the intent to turn it into a completed game for sale. As the original however with the inclusion of multiple environments, better AI, refuel dropships, different turrets, friendly AI behaviour, A roster of pilots and a plot involving rival factions who do battle on the earth as their chosen combat zone.It even had a tutorial. It was abandoned due to the realisation that the CBCFoundation's inability to use hardware rendering had made it effectively obsolete. I'd also come to the conclusion that it wasn't that much fun to play.

  • Language: Object Pascal
  • Framework: CBCFoundation, SDL
  • OS: Windows, Linux
  • Status: Incomplete - Abandoned


Crashblock

Control a person inside a game of Tetris. The person clambers and vaults over the blocks in the arena to get into positions and calls the blocks into position and rotates them. The blocks are held by a chain of increasing fragility - it will eventually snap sending the block crashing down. The player can also request the drop however in either case, it's best to be out of the way when they fall or you'll get squashed. Multiple levels, 4 environments, power-ups. Character graphics were captured from real-time video and roto-scoped. Winner of the Pascal Game Development group's 2007 competition. Published in 2008. This was the last game I wrote using the CBCFoundation and Pascal for that matter. The CBCFoundation's inability to handle hardware rendering without a massive upgrade almost killed it, but it was the advent of C# and pascal's descent into obscurity which finished it off.

  • Language: Object Pascal
  • Framework: CBCFoundation, SDL
  • OS: Windows
  • Status: Complete - Released for sale.


SUOF: Subtle Use of Force - Mobile

A conversion of the DOS based vertically scrolling shooter. I started it as an exercise in getting a mobile game developed, to understand the technical requirements as well as the development process. I hooked in the tilt controls to act as steering and on screen buttons for firing. Unfortunately, it was slow and clunky requiring far more work than I had time for at the time. It also ran differently on different phones. It served as a insightful prototyle.

  • Language: Java
  • OS: PC MSDos. 
  • Status: Incomplete - Abandoned

Reversion Bureau

A science experiment has gone horribly wrong and you are called in to make it all better. Effectively a spiritual reboot of Anomalous. A platform puzzle game using live action footage captured against a greenscreen. Multiple characters and a story. This game is still in development but features physics as well as logical puzzles. A key feature of the game is that the main character does not resort to violence - instead solves problems using intelligence, the environment and science.


  • Language: LUA
  • Framework: MOAI
  • OS: Windows, OSx, OUYA
  • Status: In Progress

SchemeWars

Control a person inside a game of Galaga. The live action greenscreen captured person fires energy bolts from their hands at increasingly difficult waves of enemies. Complete with Boss creatures, all aliens have their own set of abilities and tricks. Completed and presented at an Insurance trade show.

  • Language: LUA
  • Framework: MOAI
  • OS: Windows, OSx, OUYA
  • Status: Complete - Released for Trade show.


ROO!

An endless runner where you have to rescue little Timmy from the well. Designed to be completely cross platform and created during a GameJam in January 2015. The game is notable for it's responsive controls, Spine animation and speed.The game was polished up over a period of 3 months and released on Android, OUYA and iOS.

  • Language: C#
  • Framework: Monogame
  • OS: Android, iOS, OUYA, Windows
  • Status: Complete - Released for sale.


Untitled Block Puzzle

We have a project on the go at the moment, which we'll announce shortly. The result of the second Songbird Creations Game Jam.

  • Language: C#
  • Framework: Monogame
  • OS: Android, iOS
  • Status: In Progress - Prototype


Sunday, 28 September 2014

Box2D Raycasting with Category Masking with MOAI

What is Ray Casting?

Ray Casting is a technique used to determine whether something intersects a line drawn between one point and another. Normally Box2D uses circles, rectangles and polygons to determine collisions and resolve the forces and positions appropriately. However sometimes you just want to check for collisions along an imaginary line.

Imagine a Laser Pointer

One example for this is if you imagine a laser pointer.
Its beam is emitted from the end of the laser pen and it continues until it hits the wall at the far end of the room and leaves a pleasant red dot.

Should something break the beam, the red dot shows on the object breaking the beam and no longer on the wall.

Before MOAI 1.5

For a long time, MOAI did not support the ray casting features of Box 2D. Version 1.5 supports the closest raycast implementation where the closest object on the path of the ray is returned.

The Closest raycast feature is very much like the laser pen example. A ray is cast and the first thing which intersects the ray is returned.

A lot of the time, this is all you need.

It will find the closest Box2D fixture intersecting the ray no matter what it is.

Category Masking?

I needed something a little extra. Box2D supports categories. This is so you can designate an object as a particular type of thing so it can be included or excluded in specific collisions.

For my game I have several categories for objects.

  • FLOOR = 1
  • PLAYER = 2
  • OBJECT = 4
  • MONSTER =8
  • SWITCH = 16
  • POWERUP = 32

My laser beams should only be stopped by Players, Monsters and the Floor. Objects, Powerups and Switches should not get in the way - let alone be blown up by lasers.

I need a mask to filter only the categories I'm interested in.
FLOOR + PLAYER + MONSTER = 11

By performing a bitwise AND against the category for the object intersecting the ray and the mask, we can check to see if we're interested in it.

Here's a little binary refresher so you can see why the mask works.

Floor   = 00000001
Mask    = 00001011
Yup

Player  = 00000010
Mask    = 00001011
Yarp

Monster = 00001000
Mask    = 00001011
Yessir

Switch  = 00010000
Mask    = 00001011
Nope

However... 

Box2D doesn't support category masking for RayCasts, even though it supports categories and masks for all other types of collision detection.

This meant that even with the implementation in MOAI release 5, I couldn't use the Box2D ray casting. In fact, it meant I couldn't use Box2D* at all without making some changes.

*I'm using Box2D v 2.2.1 within MOAI - the most recent appears to be 2.3.0 (as of time of writing) however it too does not support masking.

So I modified Box2D to suit.

UDiff for Box2D 2.2.1


 3rdparty/box2d-2.2.1/Box2D/Collision/b2Collision.h     |  1 +
 3rdparty/box2d-2.2.1/Box2D/Collision/b2DynamicTree.h   |  1 +
 3rdparty/box2d-2.2.1/Box2D/Dynamics/b2World.cpp        | 18 ++++++++++++++++--
 3rdparty/box2d-2.2.1/Box2D/Dynamics/b2World.h          |  3 +++
 3rdparty/box2d-2.2.1/Box2D/Dynamics/b2WorldCallbacks.h |  2 +-
 5 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/3rdparty/box2d-2.2.1/Box2D/Collision/b2Collision.h b/3rdparty/box2d-2.2.1/Box2D/Collision/b2Collision.h
index 8bb316c..62c7ee8 100644
--- a/3rdparty/box2d-2.2.1/Box2D/Collision/b2Collision.h
+++ b/3rdparty/box2d-2.2.1/Box2D/Collision/b2Collision.h
@@ -147,6 +147,7 @@ struct b2RayCastInput
 {
  b2Vec2 p1, p2;
  float32 maxFraction;
+ uint16 maskBits;
 };

 /// Ray-cast output data. The ray hits at p1 + fraction * (p2 - p1), where p1 and p2
diff --git a/3rdparty/box2d-2.2.1/Box2D/Collision/b2DynamicTree.h b/3rdparty/box2d-2.2.1/Box2D/Collision/b2DynamicTree.h
index 0787785..ed4afce 100644
--- a/3rdparty/box2d-2.2.1/Box2D/Collision/b2DynamicTree.h
+++ b/3rdparty/box2d-2.2.1/Box2D/Collision/b2DynamicTree.h
@@ -254,6 +254,7 @@ inline void b2DynamicTree::RayCast(T* callback, const b2RayCastInput& input) con
  b2RayCastInput subInput;
  subInput.p1 = input.p1;
  subInput.p2 = input.p2;
+ subInput.maskBits = input.maskBits;
  subInput.maxFraction = maxFraction;

  float32 value = callback->RayCastCallback(subInput, nodeId);
diff --git a/3rdparty/box2d-2.2.1/Box2D/Dynamics/b2World.cpp b/3rdparty/box2d-2.2.1/Box2D/Dynamics/b2World.cpp
index d77e80a..b3497e1 100644
--- a/3rdparty/box2d-2.2.1/Box2D/Dynamics/b2World.cpp
+++ b/3rdparty/box2d-2.2.1/Box2D/Dynamics/b2World.cpp
@@ -1013,7 +1013,7 @@ struct b2WorldRayCastWrapper
  {
  float32 fraction = output.fraction;
  b2Vec2 point = (1.0f - fraction) * input.p1 + fraction * input.p2;
- return callback->ReportFixture(fixture, point, output.normal, fraction);
+ return callback->ReportFixture(fixture, point, output.normal, fraction, input.maskBits);
  }

  return input.maxFraction;
@@ -1023,7 +1023,7 @@ struct b2WorldRayCastWrapper
  b2RayCastCallback* callback;
 };

-void b2World::RayCast(b2RayCastCallback* callback, const b2Vec2& point1, const b2Vec2& point2) const
+void b2World::RayCast(b2RayCastCallback* callback, const b2Vec2& point1, const b2Vec2& point2 ) const
 {
  b2WorldRayCastWrapper wrapper;
  wrapper.broadPhase = &m_contactManager.m_broadPhase;
@@ -1032,6 +1032,20 @@ void b2World::RayCast(b2RayCastCallback* callback, const b2Vec2& point1, const b
  input.maxFraction = 1.0f;
  input.p1 = point1;
  input.p2 = point2;
+ input.maskBits = 0;
+ m_contactManager.m_broadPhase.RayCast(&wrapper, input);
+}
+
+void b2World::RayCast2(b2RayCastCallback* callback, const b2Vec2& point1, const b2Vec2& point2, const uint16 maskBits ) const
+{
+ b2WorldRayCastWrapper wrapper;
+ wrapper.broadPhase = &m_contactManager.m_broadPhase;
+ wrapper.callback = callback;
+ b2RayCastInput input;
+ input.maxFraction = 1.0f;
+ input.p1 = point1;
+ input.p2 = point2;
+ input.maskBits = maskBits;
  m_contactManager.m_broadPhase.RayCast(&wrapper, input);
 }

diff --git a/3rdparty/box2d-2.2.1/Box2D/Dynamics/b2World.h b/3rdparty/box2d-2.2.1/Box2D/Dynamics/b2World.h
index 965a366..d910e23 100644
--- a/3rdparty/box2d-2.2.1/Box2D/Dynamics/b2World.h
+++ b/3rdparty/box2d-2.2.1/Box2D/Dynamics/b2World.h
@@ -121,6 +121,9 @@ public:
  /// @param point2 the ray ending point
  void RayCast(b2RayCastCallback* callback, const b2Vec2& point1, const b2Vec2& point2) const;

+ void RayCast2(b2RayCastCallback* callback, const b2Vec2& point1, const b2Vec2& point2, const uint16 maskBits ) const;
+
+
  /// Get the world body list. With the returned body, use b2Body::GetNext to get
  /// the next body in the world list. A NULL body indicates the end of the list.
  /// @return the head of the world body list.
diff --git a/3rdparty/box2d-2.2.1/Box2D/Dynamics/b2WorldCallbacks.h b/3rdparty/box2d-2.2.1/Box2D/Dynamics/b2WorldCallbacks.h
index 82ffc02..a485d8c 100644
--- a/3rdparty/box2d-2.2.1/Box2D/Dynamics/b2WorldCallbacks.h
+++ b/3rdparty/box2d-2.2.1/Box2D/Dynamics/b2WorldCallbacks.h
@@ -149,7 +149,7 @@ public:
  /// @return -1 to filter, 0 to terminate, fraction to clip the ray for
  /// closest hit, 1 to continue
  virtual float32 ReportFixture( b2Fixture* fixture, const b2Vec2& point,
- const b2Vec2& normal, float32 fraction) = 0;
+ const b2Vec2& normal, float32 fraction, uint16 maskBits) = 0;
 };

 #endif


As you can see, the changes merely extend Box2D's raycast feature to include a request for a specific set of maskBits.  Box2D doesn't perform any filtering internally with this change.

Category checking against the mask will be done within MOAI's implementation coming up next.

Note also that I create a function called RayCast2 which can be called with the maskBits parameter. This is just in case the Original RayCast function is used internally by Box2D and to ensure that other programs using it won't be broken by this change.


Initially it felt like overkill to modify Box2D to just pass a number through and back again. However this is required because the raycast function uses a callback to notify the program that it found something - this callback doesn't have any context as to how it's being called really to know what type of fixture you're looking for.

So apart from hard coding it to ignore sensor type fixtures, you're stuck just returning the closest object of any category unless you pass the mask through to the callback function.

Basically, Box2D doesn't know to inform the callback function that you're really only interested in UFOs and it can ignore Clouds.

Here's the UDiff for the MOAI code 

(Note patch is for 1.4r2 not for MOAI v1.5 - although the change is simple to apply to 1.5 )

 src/moaicore/MOAIBox2DWorld.cpp                  | 104 +++++++++++++++++++++++
 src/moaicore/MOAIBox2DWorld.h                    |   1 +

 2 files changed, 105 insertions(+)

diff --git a/src/lua-headers/run.sh b/src/lua-headers/run.sh
old mode 100755
new mode 100644
diff --git a/src/moaicore/MOAIBox2DWorld.cpp b/src/moaicore/MOAIBox2DWorld.cpp
index 943cbf0..20b39fe 100644
--- a/src/moaicore/MOAIBox2DWorld.cpp
+++ b/src/moaicore/MOAIBox2DWorld.cpp
@@ -46,6 +46,8 @@ MOAIBox2DPrim::MOAIBox2DPrim () :
  mDestroyNext ( 0 ) {
 }


+
 //================================================================//
 // local
 //================================================================//
@@ -600,6 +602,107 @@ int MOAIBox2DWorld::_getAutoClearForces ( lua_State* L ) {
  return 1;
 }

+// local
+ //================================================================//

+// RayCast modification from: http://getmoai.com/forums/post2723.html?hilit=raycast#p2723
+// Additional box2d modification to return fixtureIndex as well.
+class RayCastCallback : public b2RayCastCallback
+{
+public:
+    RayCastCallback()
+    {
+        m_fixture = NULL;
+ m_point.SetZero();
+ m_normal.SetZero();
+    }
+
+    float32 ReportFixture(b2Fixture* fixture, const b2Vec2& point, const b2Vec2& normal, float32 fraction, uint16 maskBits)
+    {
+        
+ b2Filter filter = fixture->GetFilterData ();
+

+ //MOAILog ( state,MOAILogMessages::MOAIRayCast_MaskBits, maskBits );
+ if( (filter.categoryBits & maskBits) != filter.categoryBits )
+ {
+ return -1; 
+ }
+ /*if( ( MOAIBox2DFixture* )fixture->IsSensor()){
+ return -1; //filter
+ }*/
+
+ m_fixture = fixture;
+        m_point = point;
+        m_normal = normal;
+
+        return fraction;
+    }
+
+    b2Fixture* m_fixture;
+    b2Vec2 m_point;
+    b2Vec2 m_normal;
+};
+
+//----------------------------------------------------------------//
+/**     @name   getRayCast
+        @text   return RayCast 1st point hit
+
+        @in     MOAIBox2DWorld self
+        @in     number p1x
+        @in     number p1y
+        @in     number p2x
+        @in     number p2y
+        @out    bool true if hit, false otherwise
+        @out    number  hitpoint.x or nil
+        @out    number  hitpoint.y or nil
+ @out MOAIBox2DFixture fixture that was hit, or nil
+*/
+
+int MOAIBox2DWorld::_getRayCast ( lua_State* L ) {
+ MOAI_LUA_SETUP ( MOAIBox2DWorld, "U" )
+ float p1x=state.GetValue < float >( 2, 0 ) * self->mUnitsToMeters;
+ float p1y=state.GetValue < float >( 3, 0 ) * self->mUnitsToMeters;
+ float p2x=state.GetValue < float >( 4, 0 ) * self->mUnitsToMeters;
+ float p2y=state.GetValue < float >( 5, 0 ) * self->mUnitsToMeters;
+ uint16 maskBits = ( uint16 ) state.GetValue < u32 >( 6, 0 );
+
+ b2Vec2 p1(p1x,p1y);
+ b2Vec2 p2(p2x,p2y);
+
+ RayCastCallback callback;
+ self->mWorld->RayCast2(&callback, p1, p2, maskBits);
+
+ if (NULL != callback.m_fixture)
+ {
+ b2Vec2 hitpoint = callback.m_point;
+
+ lua_pushboolean( state, true );
+ lua_pushnumber ( state, hitpoint.x / self->mUnitsToMeters );
+ lua_pushnumber ( state, hitpoint.y / self->mUnitsToMeters );
+
+ // Raycast hit a fixture
+ MOAIBox2DFixture* moaiFixture = ( MOAIBox2DFixture* )callback.m_fixture->GetUserData ();
+ if ( moaiFixture )
+ {
+ moaiFixture->PushLuaUserdata ( state );
+
+ return 4;
+ }
+ else
+ {
+ return 3;
+ }
+ }
+ else
+ {
+ // Raycast did not hit a fixture
+ lua_pushboolean( state, false );
+
+ return 1;
+ }
+}
+
 //----------------------------------------------------------------//
 /** @name getGravity
  @text See Box2D documentation.
@@ -998,6 +1101,7 @@ void MOAIBox2DWorld::RegisterLuaFuncs ( MOAILuaState& state ) {
  { "setGravity", _setGravity },
  { "setIterations", _setIterations },
  { "setLinearSleepTolerance", _setLinearSleepTolerance },
+ { "getRayCast", _getRayCast },
  { "setTimeToSleep", _setTimeToSleep },
  { "setUnitsToMeters", _setUnitsToMeters },
  { NULL, NULL }
diff --git a/src/moaicore/MOAIBox2DWorld.h b/src/moaicore/MOAIBox2DWorld.h
index 61a6641..7d0880c 100644
--- a/src/moaicore/MOAIBox2DWorld.h
+++ b/src/moaicore/MOAIBox2DWorld.h
@@ -98,6 +98,7 @@ private:
  static int _getAutoClearForces ( lua_State* L );
  static int _getGravity ( lua_State* L );
  static int _getLinearSleepTolerance ( lua_State* L );
+ static int _getRayCast ( lua_State* L );
  static int _getTimeToSleep ( lua_State* L );
  static int _setAngularSleepTolerance ( lua_State* L );
  static int _setAutoClearForces ( lua_State* L );

So there you go. Raycasts with masking.
If I only want to shoot UFOs with my lasers, not the clouds in the sky, now I can.

So how do we use this in game?

Somewhere in your game code you'll have something which creates your MOAIBox2DWorld.
You'll be calling the getRayCast method on this object.

gameworld = MOAIBox2DWorld.new ()

Then somewhere you'll need a function to actually cast the ray and return the data back.
The function returns several parameters (typical for Lua).

  • Whether the ray hit something or not, 
  • the X co-ordinate of the hit,
  • the Y co-ordinate of the hit 
  • the object with a category matching the maskBits that the ray hit.


return gameworld:getRayCast( x1,y1,x2,y2, maskBits)



Sorry for the ugly formatting - I'm sure there's a nicer way to present a UDiff.

Have fun.


Special thanks to FiveVoltHigh.com for getting me started with their initial tutorial on patching MOAI with support for RayCasts.

http://www.fivevolthigh.com/2013/10/moai-exposing-box2d-world-ray-casting-to-moai/


Wednesday, 9 July 2014

Physics Engines for things other than puzzles and explosions.




What's a Physics engine good for anyway?

I made my own Physics engine for Crashblock
 - cue rapturous applause - 
Thank you, it was hard work and there were times when I thought I couldn't resolve all of the issues, but I got there in the end. 
- applause intensifies -
It's main tasks were to prevent the player from passing through walls 
-hang on, that's a collision detection and resolution system - applause dies down slightly- 
and to simulate gravity 
- so it's basically, move everything down and use the collision detection and resolution system to stop things from falling off the level? - rapturous applause stops and crickets are heard -

Yup, that's basically all it did and it took a long time to get right; and isn't it basically what most games need?
So why do we keep re-writing the same code and why is it always hard?

I think it's because we re-write each game basically from scratch for a very specific idea.

If only there was some sort of library which could take the effort away and focus on the game...

Enter the Physics Engine

At it's heart a physics engine keeps track of entities, their energies and attributes and makes sure that changes in energy are correctly applied and objects don't move through other objects.
Come to think of it, that's quite a task.

Serious people spent serious time writing serious software to do all of this.

Something that can handle velocity, friction, acceleration, elasticity, gravity, mass and the resolution of collisions, calculating and transferring energies to other objects seems to be something that should only be used in serious games just to do it justice - anything else would be a waste right?

It is true, you can get a really good racing game written using a physics engine - but they're useful for other things too; and if you bear with me, I'll explain why I don't think it's overkill and actually very beneficial to even the simplest of games.

Most game requirements are the same

You see, the tricky parts to any game are simulating a world. Every 2D platform game does this.


Consider Mario:
Mario describes a world where a man runs along a blocky world jumping over obstacles and collecting gems. Mario must simply reach the end of each level to complete the game.

The world has physical attributes, gravity, collision detection and solid objects and destructible scenery when hit from underneath.



Consider Sonic the Hedgehog:
Sonic describes a world where a hedgehog runs at ridiculous speeds through a world filled with hazards to be jumped over, loop the loops and enemies to be killed. Sonic must reach the end of a set of levels and defeat a boss in various guises to complete the game.

The world has physical attributes, gravity, collision detection and solid objects. It also has things to increase velocity and destructible scenery when hit at a certain speed.



Consider Treasure Island Dizzy:
Dizzy describes a world with a cute egg who jumps over obstacles and tumbles when he lands. He avoids hazards and interacts with the environment. Dizzy must solve puzzles and collect items to unlock areas of the world to reach an island via a boat.

The world has physical attributes , gravity, collision detection and solid objects. It also has hidden objects to find and underwater sections.

With just these three different games, there are quite a lot of overlapping areas.

  • Physical Attributes 
    • Mass
    • Friction
    • Velocity
  • Gravity
    • Global
    • Local
  • Collision Detection
    • Projectiles
    • Hazards
    • Hidden objects
    • Zones
  • Solid Objects
    • Static
    • Destructible
    • Movable
For just these three games, the same problems were solved in different ways to simulate a world and to provide the game mechanics.

Back when these games were made, there really wasn't much of a choice; You made a game engine for a game or series of games and you optimized it to within an inch of it's life. 

Having a common system (if one existed) would have introduced inefficiencies. The simulations needed to be as bare bones as possible to be as fast as possible as every CPU cycle counted. That means bespoke code each time.

Those days are mostly gone. Processors are powerful and memory is plentiful. 
Games are often written in cross platform languages where you have little control over the actual implementation at the machine level. The chances are that a Physics System will be written in a more efficient way to any code you or I could write ('Serious People' remember)

So why do so many people still write their own physics simulations?

Well, It could be because it seems like overkill to use something so powerful for a simeple game. 
Or there's the challenge of rolling your own. There are a lot of interesting mathematical problems to get your head around. But for me, it's a distraction to the game. It's a problem someone else who is possibly much smarter than me and a whole lot more interested in solving said problems than I am.

I choose to use an engine.

This decision is fairly recent however. But now I've seen the light, I'm sold on the benefits. I'll never roll my own again.

What are the benefits of using a generic physics engine over rolling your own to your specific needs?

Collisions


Writing a collision detection system is to be fair - Tedious - and at it's most primitive, involves testing each object in your game with other objects in your game to check if they collide. 

The mechanism you use for this will have a massive impact on the performance of your game.

From the outside it seems simple enough so it's a common thing to write early on. 
The most common is a simple bounding box test.




You can do broad testing using rectangles to check if any corner of one object intersect with any other, hopefully this means that you've zoned your level otherwise you'll be checking a lot of objects. 
As you can see, the bounding box test is clearly not good enough to detect accurate collisions with the planes.

Then what happens when you collide? Do you need to do more granular collision checking? Pixel level? Polygonal? With each step comes more work. 



Pixel level checking is more accurate but old-school and was always CPU intensive. 
With more and more work being done on the graphics card, you don't have access to pixels these days. So you're more than likely looking at a collision mesh.


Then what happens when you've detected the collision? Do you let each object know about it and allow them to decide the outcome? Do to compute the energies exchanged as part of the collision and apply the resulting energies to the objects? 

What about really fast moving objects? Will you implement some form of ray-casting? Do you care about transferring rotational forces or velocities to your objects as a result of collision?

Are all objects Solid? Do you need sensors? Will you have Passive or Active checking?

Can all objects move or do you have static objects which cannot move no matter what?

Just this first part has uncovered a mountain of work. 

These decisions will need to be made before the game development can begin. or you can let a Physics engine do it for you.

X = X + 1 // Movement

Most early games have a section which reads something like this:
If Left is pressed Then Player.X = Player.X - 1
If Right is pressed Then Player.X = Player.X + 1

This code normally evolves to:
If Left is pressed Then Player.SpeedX = -1
ElseIf Right is pressed Then Player.SpeedX = 1
Else Player.SpeedX = 0
For each object in game
object.X = object.X + object.SpeedX

The origins of a physics system. You are tracking velocity in the X axis.
With a physics engine, you can apply an impulse to an object and have it calculate the energies appropriately.

Collisions Pt2 Sensors

The Physics Engine I wrote for Crashblock was also used in a game which was tragically shelved called Guns-Reloaded. 

The AI for enemies was assisted by attaching sensors around an enemy tank which could inform the tank's brain of things like incoming projectiles and dangerous terrain. This meant that the enemy flying tanks could in theory fly close to rocks but not close enough to become damaged by collisions. It also meant they could raise shields to save themselves. 

The data from these sensors was fed into an AI routine and appropriate behaviour was determined. All in all, it worked pretty well.  

Unfortunately, the game failed to mature but the lessons learned from that were carried on to a recent game which I did complete, called SchemeWars. 

In that game aliens were aware of their own positions and the position of the ground as well as dangerous objects flying towards them so they could defend themselves. They also used other collision objects to keep each-other a nice distance from other aliens.
This behaviour was much easier to code that with Guns-Reloaded as I was using a Physics Engine.

Box2D is fast and awesome, you should use it.



I first heard about Box2D when I first saw a game called Crayon Physics. A simple game where you draw objects in order to get a ball from one place to another. 
It was very clever and used the majority of Box2D's features.



I seemed to be a perfect fit for that game, but it never occurred to me to use it in a platform game.
I started building the Reversion Bureau (working title) and again, I rolled my own physics and collision detection within the MOAI framework early on; not giving a second thought to the Box2D implementation already built in. My collision code sucked. It was buggy and it was inflexible.



So one day after reading a book from the writers of MOAI, I gutted my game and implemented everything using Box2D. Suddenly, I had perfect collision detection, silky smooth movement and slopes (gasp!). The previous collision code used the tile set and slopes would have required specialised code.
 

This is a screenshot from a very early build of the game with a debug layer showing the collision rectangles. Anything collidable has a green hue and 2 lines (green and red ) showing it's orientation. 
As you can see if you look closely, there is a rectangle around the red guy on the right. That's his collision rectangle. 

There's also a little block underneath him, intersecting the floor. This little block is a sensor attached to the sprite to detect the floor so that the sprite can see whether it is falling or standing; very useful.

There's a block to the left over a door, this is an interaction sensor.

So in this one screenshot you can see Rectangular collisions blocks, polygonal collision blocks, sprite collision blocks and sensors; and it's FAST!.

This does involve a bit more work building your maps in such a way as to provide an object layer to create the collision blocks and polygons. 

Tiled does this very nicely.

The end result being a smooth and reliable collision resolution system, far better than anything the average developer could write as well as accurate simulations of bounce, torque, friction, gravity.. pretty much anything you need to build a game world - realistic or cartoon.


In Closing


Physics Engines are amazing and useful, they're not just for realistic simulation games and you should absolutely consider using one if you're serious about making any game.. spend your energy wisely and don't reinvent the wheel... literally.


Wow that was a long blog post.







Wednesday, 2 July 2014

Building MOAI for Android and OUYA - all in one.

Building MOAI for Android.


Some things you’ll need before you start.


Patience and Attention to Detail - There are a lot of steps, thankfully once you’ve completed the earlier steps, you won’t need to repeat them. The steps have to be carried out accurately and while you can repeat them, they delete and recreate directories in some cases, so be sure you’re following the correct steps..


An existing runnable MOAI project. There are example projects to use, but as you’re at the point of building for Android, it is probably safe to assume that you have a project ready to at least test on Android.


It’s quite simple once you’ve got the hang of it.


Installing the Environment



Install CYGWIN (Install everything, MOAI uses a bunch of modules, be safe and get them all)
Install adt (Eclipse IDE with built in Android SDK and plugins)
(install to c:\adt-bundle-windows-x86_64)
Install android NDK (copy into subdirectory of adt-bundle-windows-x86_64)
Install Apache ANT (install to c:\apache-ant )


Add ant directory to your path
Add ndk directory to your path


You can use the [Start]->[Control Panel]->[System]->[Admin System Settings]->[Advanced]->[Environment Variables] and edit the value of the path variable.
(Make a copy of the previous path first before you edit as it’s hard to repair if you break it)


or you can use the command line

It’s important to get these 2 directories added to your path otherwise all sorts of things will go wrong as the build process won’t be able to find things it depends on.


Start cygwin


The Cygwin terminal places you in your user’s home directory on your the virtual linux.
To get access to your filesystem you need to:


cd /cygdrive/c


This places you at the root of your hard drive (C:\ in DOS speak)


Optional: If you already have a MOAI source codebase you want to work from,
you can use that instead.
Get the most stable MOAI from the git repo into c:\moai-dev


git clone git://github.com/moai/moai-dev.git


Once the source code for MOAI has been retrieved to moai-dev


cd /cygdrive/c/moai-dev/ant   
(remember in cygwin / takes you to the root of cygwin - not the root of C: )


Run the script to compile MOAI and generate the project structure.
(this will trash any previous projects - be warned)
Pay attention to any errors, this part will fail if anything is wrong with your environment settings.


./make-host.sh -p com.yourdomain.moai  


(make sure yourdomain does not contain [-] characters, it breaks java when compiled as it can’t be used in a namespace..


Changing Settings files.



modify settings-local.sh file.

Set the android_sdk_root to point to your android SDK.
modify the src_dirs to point to your game code.


(note that the path is to be visible to cygwin e.g. “cygdrive/c/gamedev/awesomegame/” )


Modify settings-global.sh file


change the requires=( … ) line to read just


requires=( “miscellaneous” )


Save the changes to the files.


Run the script to build the project file.


./run-host.sh


If this works properly, you’ll have the files you need to start a project.


Bear in mind that cygwin may not have created the directories with the correct permissions. So to save yourself a lot of heartache, set the permissions on the untitled-host folder to give yourself permissions to add to it modify etc. You can also rename it to something more suitable.


Once you’ve completed this section without any issues, you shouldn’t have to repeat this unless you’re re-compiling the MOAI source.

Compiling the Android Project



Start ADT and click the file menu, choose Import.
Then navigate to the directory c:\moai-dev\ant\untitled-host/Host/build/project
If you moved your host to somewhere else, then use that directory.


At this point, your game files should be in the Host/build/project/assets folder.


Once you have the project imported into ADT, you should be able to run it as an Android application.


Note: I’ve noticed a permissions issue when I try to build  the APK, if you get messages saying that you can’t add to the apk, then you need to set the permissions on the folders again as the permissions didn’t inherit when the new build folders were created.



Building Moai for OUYA

To build for the OUYA console, you follow the exact procedure for a standard Android build but with source code (for now until MOAI includes OUYA code in it’s standard host) .


Bear in mind that this is an unofficial Fork of the MOAI engine and may not have newer fixes or features.
The git repo is at: https://github.com/krusmir/LionK1tty-based-moai-dev

krusmir/LionK1tty-based-moai-dev



Once you’ve grabbed the repo either with git or by downloading the ZIP and saving it to c:\moai-dev
(or anything you need, personally mine is called c:\moai-dev-ouya so I can have both Android and OUYA builds )


You can build the project using the steps above. The only change being that instead setting
requires=( “miscellaneous” )
instead you need
requires=( “miscellaneous” “ouya” )


OUYA Specific development



Deploying to an OUYA

Take a micro-USB cable and connect the OUYA to your PC.
Windows will not be able to install the driver initially - so you’ll have to follow instructions on the OUYA web site on how to connect it.


You’ll need to make sure your Android SDK has the Google USB driver installed.
In the directory ( atdbundle/sdk/extras/google/usb_driver/android_winusb.inf), make sure you add


;OUYA Console  
%SingleAdbInterface% = USB_Install, USB\VID_2836&PID_0010  
%CompositeAdbInterface% = USB_Install, USB\VID_2836&PID_0010&MI_01


to the [Google.NTx86] and [Google.NTamd64] sections and save it.


This video explains the steps http://www.youtube.com/watch?v=454JFvFTxww


Handling Controllers.



Here’s a handy table of controls and how they’re mapped along with a brief description.
The icons are from the OUYA Dev kit. https://devs.ouya.tv/developers/docs/interface-guidelines


There are listeners which have to be defined to see the OUYA events.


MOAIOuyaAndroid.setListener ( MOAIOuyaAndroid.OUYA_MOTION_EVENT, onGenericMotionEvent )
MOAIOuyaAndroid.setListener ( MOAIOuyaAndroid.OUYA_MOTION_EVENT_TOUCHPAD, onGenericMotionEventTouchpad )
MOAIOuyaAndroid.setListener ( MOAIOuyaAndroid.OUYA_BUTTON_DOWN, onOuyaButtonDown )
MOAIOuyaAndroid.setListener ( MOAIOuyaAndroid.OUYA_BUTTON_UP, onOuyaButtonUp )


The event handlers are defined as:


function onGenericMotionEventTouchpad(touchpadX, touchpadY, player)
end


function onGenericMotionEvent(leftAxisX, leftAxisY, rightAxisX, rightAxisY, l2Axis, r2Axis , player)
end


function onOuyaButtonDown (keyCode, player)
end


function onOuyaButtonUp (keyCode, player)
end


You’ll note that the player number is passed as the last parameter. This is 1 to 4.
Also, there is no way to directly query the state of the sticks or buttons, instead you get the events when something happens.


Also note that the Java code handling the sticks takes the deadzone into account. So you need only check for values in the -1 to +1 range in either axis.

Button
OUYA Name
Typical Use
Maps to MOAI
O
The OK/Select button
Button code 96
U
The Secondary OK button
Button code 99
Y
The Tertiary OK button
Button code 14
A
A - The Cancel / Back button
Button code 97
D-Pad
Used for accurate directional control.



Button code 21


Button code 22


Button code 19


Button code 20
L1
Left Shoulder Top
Button code 102
L2
Left Shoulder Bottom
General motion l2axis
L3
Left Analog Pressed.
button code 107
LS
Left Analog Stick
General motion leftAxisX leftAcisY
R1
Right Shoulder Top
Button code 103
R2
Right Shoulder Bottom
General motion r2axis
R3
Right Analog Pressed
Button code 107
RS
Right Analog Stick
general motion rightAxisX rightAxisY
Touchpad
The Touch Pad. Acts as a touch screen.
motion event touchpad touchpadX touchpadY
System
The System button - Used for pause menus, be aware that pressing this button for more than a couple of seconds quits the game
Button code 82


Here’s a handy list of constants:


AXIS_L2 = 17
AXIS_LS_X = 0
AXIS_LS_Y = 1
AXIS_R2 = 18
AXIS_RS_X = 11
AXIS_RS_Y = 14
BUTTON_A = 97
BUTTON_DPAD_DOWN = 20
BUTTON_DPAD_LEFT = 21
BUTTON_DPAD_RIGHT = 22
BUTTON_DPAD_UP = 19
BUTTON_L1 = 102
BUTTON_L2 = 104
BUTTON_L3 = 106
BUTTON_MENU = 82
BUTTON_O = 96
BUTTON_R1 = 103
BUTTON_R2 = 105
BUTTON_R3 = 107
BUTTON_U = 99
BUTTON_Y = 100

In App Purchases

The business model for OUYA has always been Free to Play. This doesn’t mean Free games however, it is perfectly fine to offer a Free to play Demo of a game which requires payment in order to continue or even a Free-To-Play game which offers in app purchases for in-game-items.


Purchases and card details are handled through OUYA’s market place. All the game has to do is talk to it.

Checking purchases

When the game runs, after a purchase has been made - it’s important to check to see if the game has been purchased or not. Part of the ODK deals with this.



Sources and Thanks

Thanks to gamesfromscratch for getting me through the build process so I could create this document. http://www.gamefromscratch.com/post/2012/08/28/Setting-up-a-Moai-Android-host-build-environment.aspx

Thanks to Krusmir for putting the OUYA MOAI branch together