Monday, July 25, 2011

Rendering results... WAHOO!

Wow!  I can't believe how easy rendering is and the HUGE improvement I had versus the Box2D renderer.  I had it in my mind that it would be overly complicated, but it's that's not the case at all.  The results are so good that my conveyor belt actually WORKS on my phone.  That's great because I've got a couple of cool ideas for some levels using this construct.

My (simplistic) design, as mentioned in the previous post, is working great.  I created a new renderer class that is passed the the Box2D world instance.  From here, I get the list of bodies that are in the world.  I thought that I would have to iterate over all my fixtures in order to get things to appear.  That's not really the case.  Although your object may be comprised of several polygons (especially in the event that you want to a concave type object), your actual object is a single entity.  If you have a texture that 'fits over' that entity, then you are all set.  Much easier than trying to iterate over the fixture list to define individual elements!

I added some info to my user data class -- object texture, size, origin, and color.  The renderer uses these to scale textures appropriately.  When I get the real textures drawn up, it will use those instead.  I wanted to implement scaling because some of my objects don't have a predefined size at compile time (platforms have variable length, gears have variable radius, etc.)  Other objects, on the other hand, will have static sizes so handling those should have less of an impact on CPU time when I define the 'real' textures.

I added a grand total of 2 textures for my own debugging - one shape for circles and one for squares.  I also added a simple line so I can see rotation.  See the screenshot below for an example:


Observations:

1) I had defined some objects with rotation and instead of rotating the object, I rotated the fixture.  This resulted in rendering images that were out of whack with the body (a vertical platform, for example, rendered a texture horizontally).  Bad!  This was easily corrected by setting the shape's rotation to 0 and the body's .angle parameter to the desired angle.  I love quick fixes like that.

2) I need to have ordered rendering. I have some instances where objects overlap.  Sometimes the player's arm/gun is rendered before the body and sometimes it is rendered after.  You either see the gun peaking out when it is rotated or you see it 'correctly' on top of the player.  I need to correct this.  Since I'm iterating over the entire world of objects, I probably will skip this special case and have the player object render itself separately... it knows to draw the player body and then the arm next.  Skipping should be a snap because my user data includes object type info.

3) My fps on my phone on the conveyor belt map was on the order of 14 fps using the debug renderer.  Using my renderer, my fps shot up to close to the max -- 50-60 fps.

4) The screenshot above shows a capture of my game running on the desktop.  The fps says 4774.  With the debug renderer, I was getting 1/4 of that... say around 1400 fps or so.  Notably slower than what I am getting right now.  Most of the operational time was spent rendering joints (40%+).

5) This doesn't obsolete my usage of the debug renderer.  I can always run that AFTER I do my rendering to 'overlay' what the physics engine is thinking it should be displaying.  That's a pretty neat trick.

That's all for now. All in all, I'm pretty happy I got this working.  It was a big disappointment yesterday to see that the conveyor belt killed things!

Rendering

So, yesterday was a major downer with the conveyor belt failure on my phone.  I did some profiling (which is REALLY EASY using the DDMS tool in Eclipse), and the majority of the time was spent rendering / drawing the joints (43% of the time.)  To combat that, and to finally force myself to quit relying solely on the debug renderer, my goal today is to get a basic renderer up and running.

My idea is to use user data for defining texture regions references at object instantation.  Then, during rendering time, iterate over all the objects in the world and simply call their draw methods, accessed via the user data reference.

Sunday, July 24, 2011

5000+ downloads of the slide rule app

Just checked today and the Google Developer Console indicates that there have been 5000+ people that have checked out the slide rule app.  Cool! :)  Now... where's my money?!  Oh right, I released it free of charge.  Heh.

Today's achievement: a conveyor belt

I'm starting to work on my "Main Menu" screen.  My plan is to have some non-interactive game action going on in the background.  I drew up an idea to implement a conveyor belt.  I had three ideas for this and implemented two of them. 

The first (unimplemented) idea consists of creating a surface that detects collisions.  When an object has collided with that surface, an impulse is applied in the direction of the conveyor belt direction.  I think this would work, but seems kinda kludgy.

The second idea consists of creating several rotating circles (ie. gears).  Here's a picture of that implementation:

It works ok.  It does suffer from objects occasionally getting stuck between each gear.  I've got a 'slop' implemented so the gears aren't fighting each other -- it may take some tweaking to nail that down (maybe add joints or a filter type that prevents gear collisions?)

The third implementation took quite a while to figure out.  It deals with defining a chained set of objects (that I call the ChainLink) and two gears.  I took a bit of thinking to figure out an algorithm to define the chain link lengths and how you can programmatically adjust the width / height.  The biggest sticking point was a snafu I had with drawing the chain to revolve around the gears -- I was using degrees and the (poorly documented) API I was using didn't indicate that my units should have been in radians.  Whoops.  I ran into this before and was a bit frustrated that it was something as simple as that.  At any rate, here's an example of the conveyor belt I made up.


There's still a bit of slop to it, so I added a 'magic' variable that I named 'tension' that allows you to adjust the size of the gears.  This either tightens up a loose ChainLink or loosens up one that is too tight.  I've tried it on a couple of different sized gears / widths between gears and it works pretty well.

Saturday, July 23, 2011

Uncovered latent bugs

I've implemented my 'restart' & quit level menu buttons and uncovered a couple of bugs as result:

1) When switching screens, there is a potential bug in the frameworks that I patterned after Mario Zechner's game screen implementation.  Two methods are executed from the libgdx's render() method: update() and then present() -- in that order.  If the update() method logic decides to switch screens, the Game instance will do just that... and then run the new screen's present() method immediately upon returning to the render() method.  This could be a problem if the present() method is making the assumption that the update() has executed at least once.  I added a transition check in the Game class to ensure that a guaranteed transition will occur at the end of the Game's render() method.  The alternatives are to: ignore this behavior (most screens probably don't care) or encode the actual transition in the Screen's present() method.

2) My Level class was braindead.  Some levels included push buttons, doors, and wire lists that are instantiated when the Level class is instantiated.  When I reset the level, the lists were updated without being destroyed before hand.  Oops.  The net result was that after several instances of resetting the level, I'd get a native code error while trying to look up a prismatic joint translation.  In essence, the lists were maintaining references to dead objects (my world object is destroyed and recreated at every reset).  Yeah, that's classically what is known as a "BAD IDEA (tm)".  At any rate.  FIXED.  I added a dispose method to the parent Level class to remind me that I need to nuke those objects on level exit / reset.

Popup Menu first pass implemented

I spent the greater part of today messing around with getting a pop-up menu going and have the first pass done.  I also decided to bite the bullet (to a degree) and implement some placeholder graphics until I get far enough along where I can either spend more time working on better icons or hire someone to do them for me.

Here's what the pop-up menu looks like at the moment:
It consists of 6 graphics: 5 images for buttons and one for the background.  When the user presses the phone's menu button, it slides in from the left.  When the user hits the dismiss button on the screen, it slides out to the left.  Here's what I did to get this effect.

First off, I'm using the screen frameworks that I patterned after SuperJumper from Mario Zechner's libgdx demo suite.  Part of that frameworks includes states of the screens: GAME_READY, GAME_RUNNING, GAME_PAUSED, GAME_LEVEL_END, and GAME_OVER.  Under normal conditions, the state is GAME_RUNNING.  This performs updates and rendering - which currently includes the Box2d renderer and Box2d world step() functions.  When the user hits the menu button, the screen detects this and switches to the GAME_PAUSED screen.  This halts updates to the screen (but still allows the debug renderer to execute - which keeps the background in view).  Further, it's during this state that I allow the pop-menu renderer to execute.

The popup menu is a separate class that I named InGameMenu.  It contains a 2d scene stage, 5 buttons, a background and a group.  All the button and image items are added to a BoundGroup.  The BroundGroup acts kinda like a panel or layout.  Everything that it contains is locally referenced, and the group itself is referenced from the world coordinates.  Therefore, I can stick a button at 0,0, and then move the group itself around without having to worry about updating the button.  Pretty cool.

The popmenu also contains some simple state information indicating whether it is animating or not.  I create it such that it is off to the left side of the screen.  When it activates, the render() method simply increments the group's x parameter until it hits 0 -- meaning the left side of the screen.  To deactivate it, the render() method decrements the group's x parameter until it hits -viewportwidth/2... meaning fully off the screen.

The background graphic is a 1 pixel high x 350 pixel wide image.  I set the height to match the height of the viewport and the libgdx drivers take over rescaling it to fit.

The next bit of programming will be for me to create a scrolling pane text bit within this group (or perhaps, just switch it to another group.)

Things are starting to pick up.  I really do need to implement a whole bunch of levels.  The game frameworks are pretty much set.  I've got tweaking to do, but it's getting close!

Joytouch demo

Here's a quick shot of a level with some point rendering I did to reflect where the "joytouch" areas are.  As in: joystick + touchpad = joytouch. 

On the left hand side is a right/left button.  When you are to the left of the button, the player moves left... on the right, it moves right.  On the right hand side are several buttons.   The two buttons at top are the fire #1 and fire #2.  The bottom two are jump and grapple.  The middle button rotates the gun around its axis.  It works, but I'm not 100% happy with how the gun moves.  I've got a couple of different ideas in mind to see if I can come up with something better.



Today I'll be working on getting my pop-up menu working.  I'll be using the UI controls that have recently been added to libgdx.  I want to get a simple toggle button working and text scrolling.  We'll see how it goes.