Saturday, 5 July 2014

I should update more often.

Well, Phantom Slayer is pretty much done and dusted. I'm actually really pleased with it, and there's an awful lot of reusable code in there.

It all seems to work really nicely ; it's dead easy to build Composer Scenes, and change them, there's a library which does tutorials for games, where it sort of plonks comments on top of the game, again, pretty much automatically.

It's open source ; it's another demo for Executive really, but I'll probably build it and upload it.

https://github.com/autismuk/Phantom-Slayer

Friday, 27 June 2014

9 1/2 days

Well a fair bit has been going on ; I finished the Executive and got the state transition working, and
that now works like a simple, but proper game.

I'm working on a remake of a game called Phantom Slayer, which was originally for the Dragon / TRS80 Co-Co computer (a 6809/6847 based home computer from the 1980s).

It originally looked like the one below (and with a switch, it still does look like that), pretty much - it's a fairly simple explore a 3D Maze sort of game.

It's a useful test more than anything else (though the original game is really creepy) writing to something of a specification rather than something just knocked together to test the Executive system.

It can be sort-of played (at the moment you can walk about and teleport but not do anything else) and it is at https://github.com/autismuk/Phantom-Slayer if anyone wants to tinker with it. I will probably put it in the App stores when I've finished just for the sheer heck of it.

As it is under development, obviously, both it and the Executive are prone to change. I did make one change ; the ability to pass parameters into FSM events and through into the preOpen (think 'Create') phase of the scene manager. Though this is a backwards compatible extension ; I'm hoping that there won't be any major changes.




Wednesday, 18 June 2014

Dumb Design Decisions 101

Feeling dim this morning.

I realised I'd done something really stupid. OOP is supposed to be about Classes and Object Instances, right ? In a 'hack' designed to get round the problem of attaching game objects to instances of executives, I'd designed it so that when you created a new GameObject Class to subclass (the Executive:createClass() method) you provided an instance of a parameter.

So .... all instances of that class now belonged to one, and only one, instance of the executive.

Fortunately this dumb mistake has been fixed and the executive is where it belongs in the object constructor. When you create an object of some sort, you tell it which executive it is to be added to.

This is a hangover from SOE, which is the same basic idea, except there is one, only one, executive, it's a singleton.

I'm writing a scene sort of thing. The idea is that there is a Factory Class for executives, this is the equivalent of a Corona Scene. This factory class has a constructor/destructor (for resources), and methods to create a new 'scene' (e.g. create an executive and populate it with objects', start it, and methods to stop it, and tidy up (delete the executive). The last two don't do much, as the executives objects are responsible for actually stopping it (as in, say, Flappy Sphere, the game stops when there are no bird objects left).

These belong to a global class, probably called 'Game' which is a collection of such, and it just transitions between them using an FSM and the TransitionManager library.

To this end, I've added a couple of things ; there is a very simple finite state manager, which just maintains a list of states and states events , and broadcasts messages as you switch between them. Additionally, every executive now has, on demand an owning displayGroup object - I need this because there needs to be some way of having all the graphics in a particular setting together so  you can transition them in or out.

With a bit of luck it will be dead simple. I will end up with a FSM for the game outline, which has attached Executive Factory objects, and the FSM just switches from scene to scene automatically.

You can see the outline of this at the end of Flappy Sphere (at the time of writing)

Sunday, 15 June 2014

Flappy ... Sphere ?

I have written a separate simple game, this one called 'Flappy Sphere' (guess what it is based on ....) which includes particle effects and bitmap fonts.

This is complete and working, but I want to add an FSM library and associated Scene manager, and Flappy will become a host of that (at the moment it is a 'one scene' game, so to speak.

Flappy Sphere is about 250 lines of code (including comments), but that's with external libraries for the particle system and bitmap font.

There's not much to it really - pipes, 'bird', score, 'get ready' text and a background that pass a few messages about - so for example, the background sends a message to the bird when it is tapped.

The neat thing about this is it is trivially easy to add more birds (spheres ?) just at will, just by creating them, bit like in the 'Pong' demo. Or pipes, want 25 pipes on the screen, dead easy. You can even have more than one score and it will work (because the score is implemented by messaging)

The only code that is actually specific to multiple 'birds' is when a collision is detected and a bird blown up, it checks to see if there any bird objects in the game before ending it.

So you could add another bird just with:

Bird:new({ gravity = 100, x = 100 })

and it will just work.  Flappy Bird with several birds is really hard :) Changing the gravity for different birds is even harder.

Some things are more optical. When you move a sphere it doesn't use messaging to query for collisions, it gets a list of 'obstacle' tagged objects and asks each of them if it's hit them by calling it's 'has collided' method. It's a trade off between decoupling and efficiency. Isn' t everything ? :)

Friday, 13 June 2014

Executive is up and running.

The executive engine/framework is up and running, this is an example of it running.

There are four classes here - the bat, the score, the ball and the controller, everything is controlled by the executive.

The controller is a self contained object, so it just can be loaded and used - you require it in and attach it, and you can then access it via executive.e.controller - I decided not to use a messaging system.

Messages are used for the ball delay at the start, to update the score, and the balls each broadcast a message to 'obstacles' to check for collisions.

It allows you to switch pretty much as you want between asynchronous messages and direct messages - so for example to increment the score you can either use

self:sendMessage("score",{points = 10})

or you could with an extra line or two do it something like

exec.e.score:addScore(10)

I quite like this design. This code is almost completely unchanged from the SOE demo, except for the basic API stuff which has changed slightly.

Because objects are automatically attached (normally, the controller isn't yet) then you can simply add bats and balls as often as you want and it just works.  The main code looks like this:

Bat:new({ x = 32 }) Bat:new({ x = display.contentWidth/3 })
for i = 1,33 do Ball:new({}) end Ball:sendMessage("ball",{},1000)

Two bats, 33 balls, and a delay of 1000ms before balls receive an empty message which tells them to start moving.

One problem, which is a lua issue, is with executive objects now being non-singletons, when you require an object it doesn't know which instance of the executive to attach itself to. So at the moment it is added as a mixin (this is used for objects with non-nil metatables, like Corona display objects, see the score in the pong Demo as an example).

executive:addMixinObject(require("controller"):new({}))

i.e. require the controller class, create a new instance, and add it as a mixin object. May be a case for having an addRequireObject("controller",{}) method. I will give it some thought.

More experimental engines

I got Comet to where I want it, but then decided it was too theoretical. Coding is a mixture of structure and pragmatism, and both a classical OOP design and a pure component design are too much of one.

So I'm working on "executive" which is a combination of the two. It is an object aggregator and controller, with built in functionality - currently updating, inter object messaging and timers, which allows a semi-component approach via mixins.  Objects are tagged (the tags are recorded in the executive) and it can be queried for all objects with 'ammo' tags, or whatever.

For its frame system, tagging an object with 'update' causes it to have its onUpdate() method called on a regular basis.

It's on its second design, the first one , called SOE (Simple Object Engine) is okay, but I improved the design and cleaned it up.

None of these various engine ideas are particularly long, maybe a few hundred lines of code each.

Because the executive itself is an object, I'm going to try and build a FSM/Composer system where each scene is an Executive object, thus making the scene transitions semi automatic.

Thursday, 5 June 2014

So version 4 of Comet is now the master branch

and can be downloaded from https://github.com/autismuk/Comet - there's a very simple demo there with rotating crabs which is just really a placeholder.

Later on I should bring the controller thing back and a better commented demo.

Wednesday, 4 June 2014

I'm still not happy with it ......

So it is going into version 4.......... proper design document this time, and I know what I want to do. I'm hoping this will be the last one.

Monday, 2 June 2014

A working demo of C/E Systems

Squares and Crabs
There's now a useable demo of this system on https://github.com/autismuk/Comet.

You can see a piccy of it here. It has several components, mostly very basic - position, size, colour, coronaObject, velocity,power and so on.

Then there are two slightly more complex ones that create a sprite and a square respectively.

Because it is a hybrid, the controller isn't a component though. Partly because if it was, you'd have one every time you created an entity. What it is is a link to an instance of the controller.

So what it does is move the crabs and squares round in response to the controller, at varying speeds.

The systems are as follows :

There are position/CO and size/CO and colour/CO that update the corona object from the position, colour and size components.

There's a controller/velocity/power component that updates the velocity from the single controller instance. Power is how fast it goes, the scalar value of the velocity as opposed to the direction which comes from the controller.

Lastly there is a position/velocity component that updates the position from the velocity. This last one uses a thing called deltaTime (okay, I pinched the name from Unity ....) which scales movements to consistent units.

It did strike me that people might know what C/E systems are.

You can read about it here http://en.wikipedia.org/wiki/Entity_component_system

Basically, think of the things on the screen as entities (e.g. each crab is built out of an entity) that are built out of components, which are things like speed, position, alpha, a sprite and so on.

The nifty thing is the automation. If you add a velocity component it automatically moves the position component. If you add a controller component it starts being controlled by it. If you remove it, it takes it away again.

It sounds a bit mad, really. But one of Corona's biggest rivals, Unity3D, works pretty much like this.

Sunday, 1 June 2014

And more stuff about Entity/Components/Systems

So Comet is now in its third version.

Like many systems, ECS work okay in theory but there are often problems in practice.  One of the problems is the conceptual idea that components should be very basic, data only.

The problem with this sort of concept is it works okay up to a point, but if you want something as a dedicated component which does a lot you end up with umpteen systems to handle it.

I experimented with this in v2, which had a joystick control component (touch one), that you could just plug in and it worked as if it was (say) a square in Corona. All you had to do was something like:

spriteEntity:addC("joypad")

But what it did do was operate on the components that do work as very simple ones - coordinate pairs, velocities and so on. I had this very simple demo which was a couple of sprites with coordinate positions, velocities and sizes. You could then add the joystick component and it would update the velocities and so on automatically, which propagated into the positions, which meant in practice that you controlled the sprite with the joystick automatically.

This is, I think, the way forward, having code not so much in the components as associated with it. So your component members might be a joystickReference only, but the component has an associated constructor and destructor that create and delete it as you add or remove the component.

It seems to work quite well, though v3 (again, learning from mistakes and better engineered - I've never written an ECS framework before) doesn't do this yet it probably will soon.

In many ways, what I'm creating is a 2D Lua based version of Unity3D without the GUI interface (and without the enormous price tag)

This is what Unity does pretty much, taking components that do stuff and sticking them together. But it does it at a higher level than classic ECS systems do. All Unity really does is operate on the properties directly via the GUI, which looks very clever but actually isn't that difficult to do, it is like Visual Studio, you just expose properties of objects that you can then manipulate via a slider or checkbox or whatever. There are javascript and QT systems that do the same sort of thing.

It is a pragmatic ECS (sometimes known as a hybrid). You say, well, there are some things the model just doesn't fit, so try to use the best of both worlds. But you try to keep, as far as possible, the data driven idea - v3 does this, when you create an entity you give it a pile of data for its components (and this could be extended to tell it what components as well) but you allow simplifications like having a singleton map which you can access directly.

If you think in terms of say, Pacman, you can see how the various items in the game might be entities - ghosts, pacman, fruit, score, power pills and so on. The collisions you can do. You can control them , none of this is difficult.

The odd thing is the map. Is it one entity; or lots of entities (are all the dots entities, if so is this workable ?). All the other entities access it all the time, do you really want to put all that through a message system ?

The answer - pragmatically - is like the joystick. The map is a single entity which you can put things on, and interrogate to find out which way you can go (say). The individual dots in the maze are managed by the one entity.

If you didn't do that, and had 200 of the dots or something as individual entities, you'd have to render them all individually, you'd process them in your systems, and you'd have to check collision for all of them (or write special collision systems).

In other news (?) the font library does seem to be fairly stable, but we do seem to be having problems with BmGlyph.

Thursday, 29 May 2014

More stuff ....

Not posted much for a few days - this is what I've been up to.


  1. Bug fixing / improving / tweaking the Bitmap Font system, known as "Font Manager". Even though it doesn't. This is now perfectly useable (padding is not supported but will be added soon) and pretty stable and appears to work.
  2. There's a new repository called 'Particle Classes' which are some simple classes which wrap the Particle System in Corona.
  3. I've written a Component/Entity/System library (called 'Comet') which is an alternative game framework. This is still really in beta, but there is a demo of it in the github repository.

Saturday, 24 May 2014

Animation Manager renamed

To Coccyx. Well I got fed up with dull names. It's a little bit of the spine .....

I hope to start some more experimenting with this now I'm happy the Font tool is in a stablish state.

https://github.com/autismuk/coccyx

Friday, 23 May 2014

Re-engineered Font Manager

The font manager has been replaced by something which does the same thing, but it has been rebuilt largely from scratch.

It offers most of the same functionality, actually slightly more. The main change is that it is now a display object in its own right rather than pretending to be one. So you can use it much as if it was a display.newText() object.

The one downer is that if you turn animation on, and you rely on the system to remove it, (e.g. garbage collection in Composer) it will keep the reference to the bitmap string - it needs it to generate the animations.

So in your exit events, turn animations off on any bitmap strings you use (or remove them). If it's not animated, there's no reference.

https://github.com/autismuk/Font-Manager

List of changes

a) setScale() no longer functions. Adjust font size to suit, or scale overall.

b) there is no FontManager object, really, though setEncoding(),setTintBrackets() and setAnimationRate() still work as there is a 'pretend' FontManager. These are now all methods of BitmapString, though all affect the global state of the fonts, so setAnimationRate() sets the rate for all the bitmap strings, not just one.

c) curve and scale have been switched so they are the right way round. Previously they were 'visual' opposites.

d) FontManager:Clear() does not exist. The primary reason for this is that it maintained a reference to the object. If there is sufficient demand I will add a tracking of creation on demand approach which will do the same thing.

e) You cannot directly subclass BitMapString, because it is now a mixin.

Your new method for a subclass should look something like

local function SubclassBitmapString:new(font,fontSize)
local newInstance = BitmapString:new(font,fontSize)
.. do class specific initialisation.

.. create mixin - you can do this with a for loop as well.
newInstance.someFunction = SubclassBitmapString.someFunction

return newInstance
end

f) Curve is now a static class in its own right rather than being a method of FontManager.

Thursday, 15 May 2014

Support for tinting added.

FontManager can now tint characters - change their colours, effectively. If you have a white font, this gives you a multicolour font.

Multiline, tinting and UTF-8
support added.
There are three ways to do it - you can set the tint for the whole string using a method, you can use modifiers to change it (e.g. the e in pulse) and you can put inline colour definitions.

e.g. Hello{blue}World ! This {1,0,0.5}is {} text"

The {} can be set to any pair of bracketing characters that are not alphanumeric or a decimal point.

Both the library and demo have been updated for the new improved library - though the demo is still unchanged.


Wednesday, 14 May 2014

FontManager enhancements

Thanks to Richard9 on the forums who gave me some good ideas for enhancing the font library. It now supports the following

  • Multiline text - separate with \r or \n - this only works in forward or backward orientation ; vertically orientated text doesn't start a new line.
  • Support for extended characters. Originally it just used unicode strings (e.g. 0-255) but it can now cope with UTF-8 strings up to two bytes long - if anyone wants three or four byte UTF-8 characters please let me know and I will code it.  These are still, however, converted to unicode characters, all the font designers use unicode as far as I can tell !
  • Word and Line effects. So for example, pulse originally operated on individual characters, now you can easily pulse words in a line, or lines in a multiline, or do anything with it really :)
Richard also suggested tinting characters, which I will experiment with. I'm not totally convinced what the API should be yet, but it will be consistent with the multi-level design.

One feature of the multiline text is that in bmglyph and Glyph Designer fonts the height is often more than you think it is - there seems to be a tendency to have odd characters will really low descenders or high ascenders (?) especially if you use exotic fonts. This means the text in multiline text is further apart than looks natural. 

This actually threw me for a while, I was sure the spacing had to be a bug. It wasn't until I looked at the .FNT file that I actually realised it was right.

However, to fix this there is a new method setVerticalSpacing(scalar) which is a scalar (default value 1) applied to the vertical spacing so you can squeeze or stretch this to your hearts content.


You can see most of these things by running the main.lua and experimenting with it.

https://github.com/autismuk/Font-Manager

Monday, 12 May 2014

FontManager, small API change

Well, I don't like changing the API of something that's been released, but in this case it's necessary.  It  only affects the call to the modifiers and I suspect no-one other than me has written one yet.

It was a bad call in the first place anyway - in the modifier calls, the parameters are normal parameters, but in the extensions I have in my head it would end up with ten of them :(

What I have changed is the signature of the modifier, rather than providing the information as a parameter e.g.

function pulser(modifier, cPos, elapsed, index, length)

it passes everything except the first two as a table

function pulser(modifier, cPos, info)

the names are the same, so to use it in modifiers all you need to do is add "info." before elapsed, index and length so this:

function pulser(modifier, cPos, elapsed, index, length)
local w = math.floor(elapsed/250) % length + 1
if info.index == w then  
local newScale = 1 + (elapsed % 250) / 250
modifier.xScale,modifier.yScale = newScale,newScale
end
end

becomes this:

function pulser(modifier, cPos, info)
local w = math.floor(info.elapsed/250) % info.length + 1
if info.index == w then  
local newScale = 1 + (info.elapsed % 250) / 250
modifier.xScale,modifier.yScale = newScale,newScale
end
end

internally there is a bit of reengineering to support some new features, but externally this is the only change.

Sorry ! It shouldn't happen again.

Sunday, 11 May 2014

Experimenting with Skeletal Animation ideas.

Graphics by Ray Wenderlich
I've been experimenting with some Skeletal Animation bits and bobs. The demo shows my first go, on the right (the Elf image is from Ray Wenderlich's Spine Tutorial)

Actually it's the second go but I can't draw for toffee, you wouldn't have wanted to see the original graphics....

I wanted something Spine-esque but simpler, however great Spine is the Corona library doesn't work (v1 Graphics) and it's still £100.

This makes some simplifications for simplicity and speed. All the graphics have to be aligned vertically top-up and their anchor points are on a vertical line through that graphic, though they can be moved up and down that line - see where the anchor point is on the bottom part of the body, it's 20% inwards.

This vertical line can be moved though - if you look at the legs the vertical line is way over to the left

If you look below (perhaps) you can see the arm - having it automatically in this vertical position saves a lot of math, but it does add limitations

The arm - notice
the vertical orientation
Any of those images can be placed between any two points on the skeleton (highlighted for debugging purposes as a yellow line) and then those points can be moved arbitrarily.

The big advantage of the simplification in the graphics bit is that there is no complex munging of the image or the line to make it work, it is about 3 or 4 Corona API calls and a little bit of simple mathematics.

I plan to experiment a bit further and then once that's done see if people have any useful suggestions or ideas.

The development version is currently at https://github.com/autismuk/coccyx and should normally be in a working state though of course it is in regular development.

Saturday, 10 May 2014

A minor tweak

When I was writing the demo, I realised it would be handy if I could arbitrarily remove strings as well as add them - completely remove them from the whole system.

The FontManage controls the texts - it has an internal list of them. So if you remove a text from the view say, it will still physically be there, creating resources. It's really needed for transient displays, so suppose you pop up a screen over a game displaying some information and want to use a bitmapped font, then you can create bitmap strings on entry and remove them on exit.

None of this should affect any prior written code in any way.

Wednesday, 7 May 2014

Think it can go out now.....

Demo Program
So my font manager is ready to go, in alpha (beta ?).

Apart from the sort of running commentary here, there are two places to go - first is the demo program, shown on the right.

https://github.com/autismuk/Font-Demo

This is a quick and dirty program that displays various text effects in action, built in and coded ones. There are six (four of which are built in).

https://github.com/autismuk/Font-Manager

is the other, which is the current version of the library and has its own demo program.

All the code is commented and the library has a HTML document file.

One thing the demo doesn't show (but the demo program in the library does) is that you can transition these objects like anything else.....

Tuesday, 6 May 2014

Github Cloning issue

I did have one problem. I was using links to keep libraries in sync, there's a copy of the transition manager in the scene manager.

Git stores them as links, so if you clone SceneManager it wouldn't work, because the link goes nowhere. They are now hard copies, annoyingly.

Git does do sub projects and things, but it seems a nightmare just to have one file out of a repository and have that kept up to date.

luavadoc (sic ?)

The documentation of the libraries leaves a little to be desired (euphemism for 'rubbish') so I have been working on that ; I have created my own version of Javadoc for Lua - which is designed to operate in sync with my coding style. It's in github, but it's pretty useless if you don't code like me.

So, I've been working on the three libraries bringing them more up to scratch, commenting main.lua and other bits that needed it and so on. So far, I have only done the transition manager https://github.com/autismuk/Transition-Manager

The doc does come up as HTML, but I haven't figure out (yet) how to set up git so that html files within git display as html rather than as the raw text.

L8R: Have done the same for Scene Manager.
Even L8R: Have done the same for Font Manager.

Monday, 5 May 2014

Something close to releasable .....

Too much of this stuff will give you
a headache
I must figure out a way of saving videos from the Simulator.

Anyway, this is sort of releasable, a version 0.1 alpha, or as Microsoft would call it 'bug free final release'. It needs commenting more and documenting better, well at all :)

Also, I think I'll make it so it reads the .fnt file in directly rather than parsing it separately. And it needs a better demo than what I have here (latest state of my testing)

You can't really see it here, but the top curve is oscillating, the middle word 'pulse' is highlighting each letter in turn by blowing it up, and 'Another one' is wobbling.

These are standard effects (except for pulse) - there is a fourth at the bottom right as well.

All of these are being transitioned.to ; one of the pleasant surprises is that you can scale a view and its parts independently, so the 'pulse' is being zoomed at the same time as the letters are.

The code to do this is not too long winded. The blue bits are usual Corona stuff ; the other four colours show the creation of four different strings.  The only thing that's unusual is the pulser() function.

It works out the current character by dividing the elapsed time in ms by 360 and making it in the range 1 .. length (the string length), that character (index identifies the character) then is scaled to 2,2. If you uncomment the modifier.rotation line it spends while it is highlighted which is nifty from a demo point of view but completely unreadable. It just bangs it out there x 2 at the moment but it wouldn't be hard to make it zoom.

The thing I like about this is you can do all kinds of utterly insane things with it if you want, but if you just want a simple effect there's a library of them (currently only about six of them)

The animate() methods tell it to animate - if you don't have this it just applies it once and leaves it, so you'd get a non moving curve on "Another demo curve" for example.

https://github.com/autismuk/Font-Manager

display.setStatusBar(display.HiddenStatusBar)

fm = require("system.fontmanager")

local str = fm.BitmapString:new("retrofont",48)

str:moveTo(160,240):setScale(2,2):setText("Another demo curve")
str:setModifier("curve"):animate(4)

local str2 = fm.BitmapString:new("font2",45):setDirection(270):setText("Bye!"):setAnchor(0,0):setScale(-1,1)

local str3 = fm.BitmapString:new("demofont",30):moveTo(160,400):setText("Another one"):setScale(2,2)

str3:setModifier("wobble")
str3:animate()

function pulser(modifier, cPos, elapsed, index, length)
local w = math.floor(elapsed/360) % length + 1
if index == w then 
modifier.xScale,modifier.yScale = 2,2
-- modifier.rotation = elapsed % 360
end
end

local str4 = fm.BitmapString:new("retrofont",80):setText("pulse"):moveTo(160,240):setModifier(pulser):animate()

local t = 8000
transition.to(str:getView(),{ time = t,rotation = 0, y = 100, xScale = 0.4,yScale = 0.7,onComplete = function() --[[ FontManager:clearText()--]] end })
transition.to(str2:getView(), { time = t,x = 300, y = 400, alpha = 0.4,xScale = 0.4,yScale = 0.4 })
transition.to(str3:getView(), { time = t,rotation = 360 })
transition.to(str4:getView(), { time = t, xScale = 2,yScale = 2})

Getting there

Something of a milestone.

You can't see it on here, but the system is animating at the dual level now - so this text is moving up the screen (under the control of transition.to) while vertically scaling up and down following a sine curve (under the control of the Font Manager).

It all seems to be working very nicely.


Sunday, 4 May 2014

Dumb mistake of the week :(

Affects scene manager, transition manager and font manager.

What's wrong with this ?

_G.Base =  _G.Base or { new = function(s,...) local o = { } setmetatable(o,s) s.__index = s s:initialise(...) return o end, initialise = function() end }

This is my one line OOP. Like an idiot I modified it slightly but didn't test it thoroughly.

Answer : the initialiser which I added, s:initialise(...) works perfectly - except it initialises the passed in prototype (s) not the newly created object (o), should be.

So instead of nicely constructing a new object, it "reconstructed" the prototype.

_G.Base =  _G.Base or { new = function(s,...) local o = { } setmetatable(o,s) s.__index = s o:initialise(...) return o end, initialise = function() end }

Aarggh !

Making some progress

Progress is being made, the BitmapFont class (see picture) is now pretty much complete and tested. This is a picture of it with a sine function applied to the yScale.

The slight slant on the images is nothing to do with the font library, incidentally, it's the way the letters were when I created the working font with bmGlyph.

As usual you can see the actual demo (it spins and zooms this) in the github account https://github.com/autismuk/Font-Manager though obviously this is still very much a work in progress.

Things left to do are:

  1. The Font Manager - this tracks font usage, allows texts on a screen to be easily managed, and provides animation support.
  2. The Animation Support - the code will support this at the moment (e.g. you could make the 'curve' on the letter pictures move, or zoom in and out, or spin round (you can spin the letters individually or the whole thing).
  3. Some Animation Providers - these are some classes that provide some standard easily configurable animations and shapes. These aren't hard to write, you can pretty much make the letters do anything you want.
  4. Some sort of demo showing it working. This isn't a real demo, it's just the current state of my build - which is why the run code is still in the library - I will try to arrange it so every commit does do something, but what it will do depends largely on what I am testing at the time.

But it's looking quite promising. If anyone's wondering, this will be a freebie as well (pretty much you can do what you want with it, don't pretend someone else wrote it :) )

The guts of this demo, e.g. the bit to run it looks something like this (cut n pasted straight from the code)

local modClass = Base:new()
function modClass:modify(m,cPos,elapsed,length) 
local a = math.floor(cPos * 180*2) % 180
m.yScale = (math.sin(math.rad(a))+0.3)*3
end

display.newLine(0,240,320,240):setStrokeColor( 0,1,0 )
display.newLine(160,0,160,480):setStrokeColor( 0,1,0 )

local font = BitmapFont:new("demofont")
local str = BitmapString:new(font,44)

str:moveTo(160,240):setAnchor(0.5,0.5):setScale(1.3,1):setDirection(0):setSpacing(0):setFontSize(64)
str:setText("Another demo")
str:setModifier(modClass:new())

transition.to(str:getView(),{ time = 4000,rotation = 720, xScale = 0.5, yScale = 0.5})

This is actually more than is needed. the two lines are just drawing the lines, and the system will support fonts-by-name directly (e.g. you can write BitmapString:new("demofont",44) .  Some of the chained function calls are unnecessary (e.g. anchor is 0.5,0.5, direction is 0, spacing is 0 and you could put the 64 in the BitmapString:new() call) but just there so I can tinker with them.

The modifier (the first five lines) is implemented as a class but in can be implemented as a function as well (shorter but less flexible) and there will be a bunch of standard ones so people can have special effects without writing modifier classes/functions at all. The modifier kind of says "well, it's this character, this amount of time has elapsed, how do you want to muck about with this one ?" - in this case it's applying a sine curve to the yScale. If you applied it to yOffset the characters would move up and down but would all be the same height. In the final version (doesn't work yet) if you added elapsed into that formula the curve will move about. The standard ones will be much easier than this, you won't have to faff around with trigonometry to get some effect or other.

So you'd only need about half the code in the final version.

Saturday, 3 May 2014

Bit more work done.

On the font thing. The main thing that's vanished is displaying the text at an angle ; you can still go in any of the 4 main directions, but you can't draw text at 45 degrees (except by rotating the view, obviously). The primary reason was that it was horrendously messy in terms of recalculating the bounding box.

I can't use the anchorChildren of view group which automatically gives an anchor system, because the actual display object boxes move and change size. The library has an idea of a 'core' text item, with  x/y scale, text size and so on, which is modified on an individual basis, so individual characters have their own scale, size, rotation as well. To do this - to have a zooming character means I have to change the display object size - but this will change the bounding rectangle of the view group.

It looks like it's going to work quite well. At present, the system seems to work fine with transform.to()

There is a problem though. If you use transform.to to scale it, the individual scaling will not work, I don't think this problem is fixable. x,y,alpha and rotation are fine and will work normally, but scaling with animated scaling - say having characters zoom in and out will completely confuse the drawing system.

It's not unreasonable really, it has two different things - the animation controller and the transition controller arguing about what scale it should be.

If you don't animate the text (in the sense of animating the individual characters), scaling works fine - the system just allows you to create the text then forget about it and transition it about like you would a sprite or anything else.

Having said that if you are animating the text and scale of the text and the individual characters as well it would probably do the user's head in. There is only so much spinning and zooming it can take.

Friday, 2 May 2014

Font Manager

A bit of the Corona Simulator
The font library is starting to produce some results.

First thing I did was to write a lua script which converts the .fnt file that programs like bmGlyph produce to a lua file, so that I can require it rather than parsing it all the time.

Then I wrote a BitmapFont class which reads and stores the bitmap information, and creates image objects that can be manipulated.

This picture (from the repository https://github.com/autismuk/Font-Manager) shows the sort of thing I'm hoping to do, though this is the testing code that the BitmapFont class uses (the reason for the 'y' is to check descenders), and it doesn't show the animation, which is a bit eye-numbing :)

Basically it operates like a text item, except every character is a display object. They can be aligned horizontally or at any angle you like. There is an overall scale, horizontal and vertical (-ve flips individual letters not the whole thing). Letters can independently rotate (the 'O' of world is going in the other direction if you look closely).

Once you've done that though, additional to the standard scale and position you can apply individual scales and positions. You can see that the 'e' is scaled up and the 'w' is scaled down.  Also, the whole string has a sine curve applied to it that makes it wavy.  In the demo in the repository at the moment, these things are all being animated using enterFrame, so they are all spinning, and the 'e' and 'w' are zooming in and out.

The modifiers will be encapsulated in a function call which includes the character position and the clock, so you can either have static effects (the sine shaping) or active effects (the zooming and rotating).

At the moment it is just done by testing code, I wanted to make sure the code to position/scale/rotate the characters was pretty bulletproof first.

If you removed all these modifiers it would just display "Hello, worldy !" in a straight line neatly in the bounding box.

Besides this, while it will be an OOP library it is possible to access the view group, so that you can apply transitions to it, though only as a whole thing, the transition.to/from methods won't work on individual characters.

It's not actually useable as a library - yet - but it is available to download if anyone wants to look and/or make suggestions.

Thursday, 1 May 2014

Composer with Objects

Pretty much completed this, for first project anyway - I'm putting together reusable components for a game, rather than simply writing it. Next thing will be a library which utilises .fnt / .png files to print text in a coherent fashion, I want to be able to animate them and scale them and so on to produce Amiga Demo style effects without too much difficulty.

The Composer library is probably useable if anyone wants to play with it, but the interface might change a bit. You never quite know how useable your components are until you write something with them.

So, some examples. These all come from the demo that is there, shortened, mostly removing either print statements for debugging or scene setup code.

This declares a scene class which can be reused easily, just to create test scenes easily really.

SimpleSceneClass = sm.Scene:new()
creates a new scene. sm is the singleton instance of the Scene Manager.

function SimpleSceneClass:create()
local vg = self:getViewGroup()
self.r = display.newRect(10,10,display.contentWidth-20,display.contentHeight-20)
self.r.anchorX, self.r.anchorY = 0,0
self.r:setFillColor( 0.4,0,0 ) self.r.strokeWidth = 42 self.r:setStrokeColor(0,0,1)
        vg:insert(self.r)
        (more of the same setting up simple display stuff.)
self.item = 0
end

this is analogous to the create event - it creates objects which are insert into the view group.

function SimpleSceneClass:tap(event)
if event.target == self.text then 
self:gotoScene(self.tgt)
else
self:gotoScene("over1")
end
return true
end

this is a tap event. You can tap the text bit to go to another scene, or you can tap something else to go to an overlay called "over1". It works the same sort of way, though I do allow dimming of the background scene, or not, as you like.

function SimpleSceneClass:enterFrame(a,b,c)
self.item = self.item + 1
self.textCount.text = self.item
end

This is quite useful.  Firstly, data can be stored in a scene, and won't be lost even if the scene is created and destroyed. So self.item is a counter. The enterFrame event is called automatically by the SceneManager if this is the current scene. What this does is display a counter which increments at 30Hz. (fps rate). You don't have to set up, or remove event handlers.

function SimpleSceneClass:getTransitionType() return "flip" end

This overrides the 'exit' transition from the class, so it uses flip.

function ShortDisplayClass:create()
self:insert(display.newText("And now ...",display.contentWidth/2,display.contentHeight/2,native.systemFont,24))
end
function ShortDisplayClass:nextScene() return "thirdscene" end
function ShortDisplayClass:sceneDelay() return 2500 end

This is fun. This is a Scene class which creates the scene (as normal), but it automagically waits (2500ms, e.g. 2.5 seconds) and then goes to the scene "thirdscene". Quite nice for transient information scenes.

DemoOverlayClass = sm.ModalOverlayScene:new()

function DemoOverlayClass:create()
local c = display.newCircle( display.contentWidth/2,display.contentHeight/2,100 )
c:setFillColor( 0,1,0 )
c.strokeWidth = 2
self:insert(c)
c:addEventListener( "tap", self )
end

function DemoOverlayClass:tap(e)
self:closeOverlay()
return true
end

The worlds dullest overlay. Just displays a circle, you tap on it, and it closes the overlay. There is a non modal overlay scene class as well.

So, we'll create three scenes and an overlay and wire them together.

s1inst = SimpleSceneClass:new():setup("One","secondscene")
s2inst = ShortDisplayClass:new()
s3inst = SimpleSceneClass:new():setup("3","firstscene")
ovinst = DemoOverlayClass:new()

these are instances of scene classes. It's OOP, so you create a scene class then an instance of it (though in LUA you can actually do both with the same thing). The set up method just puts some text to make the classes visually distinguishable, the second parameter is where you go after this. ShortDisplayClass has this hard coded (it goes to thirdscene, specify in the nextScene() method).

smgr:append("firstscene",s1inst):append("secondscene",s2inst):append("thirdscene",s3inst):append("over1",ovinst)

Then we tell the scene manager what they are and what they are called. I kept the Corona idea of naming scenes, but you can use the reference if you like. And I like chaining. And templates.

smgr:gotoScene("firstScene")

.... and it does.  So we've created with this code two scenes with the counter and the overlay button (1 and 3) and the transitional automatic screen (2) and an overlay scene. None of them actually do a great deal, but they could, of course.

All this stuff, incidentally, is under the MIT license, which pretty much amounts to 'help yourself'.

Tuesday, 29 April 2014

Composer replacement

My composer replacement is coming on quite nicely. I've got the basics working, and created a special class that allows intermediate scenes to be more or less automatic - so you can create a scene which is shown for a specific period of time and then exit.

Monday, 28 April 2014

Working on my own version of Composer.

I'm working on my own version of Composer.

I have separated the Transitions into a separate library - so the transitions bit now just does a transition from one scene to another (or a scene from/to no scene), and a Scene Manager with some scene classes that uses the Transition library.

It sort of works at present - it needs some extra testing, but it allows the declaration of classes for scenes, e.g.

SceneClass = sm.Scene:new()

function SceneClass:create()
local vg = self:getViewGroup()
self.text = display.newText("Scene "..self.id,160,240,native.systemFont,32)
vg:insert(self.text)
self.text:addEventListener( "tap", self )
print("Scene "..self.id.." create")
end

function SceneClass:tap(e)
self:gotoScene(self.tgt)
return true
end

function SceneClass:setup(id,tgt) self.id = id self.tgt = tgt return self end

function SceneClass:getTransitionType() return "slideright" end

s1inst = SceneClass:new():setup("One","secondscene")
s2inst = SceneClass:new():setup("Second one","firstscene")

smgr:append("firstscene",s1inst):append("secondscene",s2inst)

smgr:gotoScene("firstScene")

So it declares a new scene class, which just plonks some text on the scene and attaches a listener to it. which goes to another scene (the 'setup' method is just to name the scene and where it goes after easily, it's a bodge for testing).

The getTransitionType() method defines the transition - it then creates two separate instances of the class (s1inst and s2inst), adds them to the known classes, and goes to the first scene (smgr is an instance of "SceneManager", sm is an instance of the SceneManager library).

It's on github https://github.com/autismuk/Scene-Manager but it is definitely a work in progress.

Icons

I find the number of icons required increasingly absurd in Apple and Android applications (obviously, this isn't Corona's fault !)

Both in generating the things and also in the clutter they put in the root directory. Really, the root directory should just contain the configuration files, main.lua and subdirectories, not 317 icons all of which are basically the same.

In an attempt to fix both I have written 'iconcreator.lua' which is a lua script file (so it requires the lua command line interpreter, it's not a Corona Application). This has one file, icon.svg, which is a vector graphic of the icon.

Vector graphics can be scaled to any size without pixellating or any other problems, save for if they get really small detail will be lost.

The script will create icons of the required sizes for Android and Apple. Ouya could be easily supported, but Ouya's icon is not square.

It will also delete the icons - so you can get rid of the things when you are developing, and run the script just before building for release, then remove them again.

You can get it here https://github.com/autismuk/IconCreator

Corona and the Model-View-Presenter pattern - Index

This is the index for my seven part short series on Model-View-Presenter in Corona.

Part 1
Part 2
Part 3
Part 4
Part 5
Part 6
Part 7

Source for the series is available from github

Corona and the Model-View-Presenter pattern (Part 7)

Welcome to the last part of the MVP Tutorial.

One of the main faults of the game is that the control system is pretty dire. It's not that easy to track the little bat with a mouse. So we're going to add a button to do the same thing.

This shows one of the advantages of separating everything and decoupling it (to some extent !). The control is purely a function of the view - if you recall from a previous part, the view detects the button click, and sends a message to the presenter saying "I've had a button click".

So all we need to do is to add a button, and get it to send that button click again - so nothing changes but view.lua, which has the following added to its initialise function.

view.scoreObject = display.newText("<score>",315,5,native.systemFontBold,32) 
view.scoreObject.anchorX,view.scoreObject.anchorY = 1,0

view.actionButton = display.newImage("button.png") -- create an action button
view.actionButton.anchorX, view.actionButton.anchorY = 0.5,1 -- position it, size it, etc.
view.actionButton.x,view.actionButton.y = 160,475
view.actionButton.xScale,view.actionButton.yScale = 0.3,0.25
view.actionButton.alpha = 0.8
view.actionButton:addEventListener( "tap",view )   -- it sends the message as well.
end

We create a new display object, put it where we want it, and make it slightly transparent. Then we add a second event tap listener. Any tap event here is routed to the view:tap function, which sends a message to the presenter.

- and that's all there is to it....

The final version is available from https://github.com/autismuk/MVP-Intro/tree/master/Part7

Thank you for reading ; any questions please feel free to ask them here, email me or ask on the forum (I might spot them).

Sunday, 27 April 2014

Corona and the Model-View-Presenter pattern (Part 6)

Welcome to the sixth part of the MVP Tutorial.  One left :)

Regarding Part 5 ; the best way of inverting the display, with the minimal amount of change, is simply to process the 'y' coordinates - replacing model.thing.y with 480-model.thing.y - the game will work exactly the same, it will just be upside down.

One of the advantages of this sort of thing is the ability to make changes without those changes having too many knock on effects. This part, and the next, will show those in practice.

Part 6 is dead simple. We are going to replace the circle with an actual picture of a ball.

This will be very very small on a 320x480 resolution, but it is possible to see it, just. If you want it bigger, you can amend the radius in the model. - the radius is part of the 'game data'.

So, we can change this without worrying about the model, or the presenter, it is just a visual change. To do so, we have to change both the initialise functions, and the update functions. This is the 'new' initialise function (the unchanged bits are, as usual in italics)

view.presenter = presenter
view.batObject:addEventListener( "tap",view )

view.ballObject = display.newImage("ball.png")

view.scoreObject = display.newText("<score>",315,5,native.systemFontBold,32)
view.scoreObject.anchorX,view.scoreObject.anchorY = 1,0
end

All we have done is take out the circle and replace it with an image. From the viewpoint of the model or the presenter it doesn't matter what it is - it could be three sprites, or drawn out of lines, it doesn't matter.

We have to update the view slightly differently - originally we provided a radius for the circle, now we provide a height and width for the sprite.

function view.update(model)
view.batObject.x = model.bat.x 
view.batObject.y = model.bat.y
view.batObject.width = model.bat.width

view.ballObject.x = model.ball.x
view.ballObject.y = model.ball.y
view.ballObject.width = model.ball.radius * 2
view.ballObject.height = model.ball.radius * 2

view.scoreObject.text = ("00000" .. model.score):sub(-5,-1)
end

Again, very minimal changes in one part - we remove the view.ballObject.radius and replaces it, updating the width and height to twice the radius.

Run it and it works. This is downloadable from https://github.com/autismuk/MVP-Intro/tree/master/Part6

The exercise, the last one, is to replace the bat with the bat graphics included in the download. Or use your own :)

In Part 7, the last part, we will replace the control (clicking on the bat) with an action button which does the same thing.

Corona and the Model-View-Presenter pattern (Part 5)

Hi, and welcome to part 5 of my seven part series.

The last exercise was to add a score to the game. We aren't tracking score, at the moment, so that needs two modifications - adding a score to the model (in model.lua, initialisation function)

model.ball = { x = 100,y = 100, dx = 1,dy = 1,speed = 10, radius = 10 }
model.score = 0 
end

and adding code to display it in view.lua (one modification to the initialise, one to the update)

view.scoreObject = display.newText("<score>",315,5,native.systemFontBold,32) 
view.scoreObject.anchorX,view.scoreObject.anchorY = 1,0
end

        view.scoreObject.text = ("00000" .. model.score):sub(-5,-1) 
end

In this part, we are going to add code to move the ball. I have decided to add the ball moving code to the presenter (the bat moving code is in the model).

Now, there are no fixed rules about this - some people believe in a very very dumb model which just has the data only (known as the "Tyra Banks design pattern" ....). Some people think all the code that manipulates and accesses the model should be in the model.

It doesn't matter too much, really, as long as there is reasonable consistency. This isn't very consistent, obviously, but that's because I'm showing what could be done.

So, in presenter.lua we need to add a call so the update method moves the ball.

function presenter.update(model, view)
presenter.model = model
model.moveBat() 
presenter.moveBall()
view.update(model) 
end

and then we need to create the ball moving method. This is very simplistic, but like the whole series it's designed to showcase concepts, not produce a real game :)

function presenter.moveBall()
local m = presenter.model.ball -- shortcut to model.
if m.dy < display.contentHeight then   -- stop moving if off the bottom
m.x = m.x + m.dx * m.speed -- move it.
m.y = m.y + m.dy * m.speed

if m.x < 0 or m.x > display.contentWidth then -- bounce off left/right sides
m.dx = -m.dx 
end

if m.y < 0 then -- bounce off top of screen
m.dy = -m.dy
end

if m.y > presenter.model.bat.y and m.y-m.dy*m.speed <= presenter.model.bat.y then
if math.abs(m.x-presenter.model.bat.x)<presenter.model.bat.width/2+m.radius then
m.dy = -m.dy -- bounce off the bat, score 10
presenter.model.score = presenter.model.score + 10
end
end
end
end

So it just bounces off the top, left and right, and the bat. You get 10 points for hitting the bat. Once its gone off the bottom it won't move any more.

With all this done, the game should work. Very simple and primitive, but it does work.

Next time we are going to make some simple changes, to show some of the advantages of this structure (hopefully). 

There is no exercise here (really) but if you want to try something, see if you can make the game play upside-down (bat at the top, goes off the top), changing as little as possible in the game :)

The complete code (without the upside down bit) is at https://github.com/autismuk/MVP-Intro/tree/master/Part5

Corona and the Model-View-Presenter pattern (Part 4)

Hi, and welcome to part 4 of my seven part introduction to Model View Presenter.

First up, the answers to the exercises from Part 3.

1) The background in this case is purely part of the view - it is purely decorative. It doesn't interfere with or even affect the game logic, or the model at all. If it was an 'active' background - say there were obstacles to bounce off, it would have some information about those in the model.

2) Changing the bat height (e.g. thickness) is also view only. In some games - say if there was a second bat half way down the screen - it could have a thickness in the model.

This time, we're going to add something to the game - the ball. The games a bit dull at the moment ... okay, it's very dull.

However, it's just going to be a ball - no actual ball movement (that's in part 5). So this involves changes to the model (the ball data) and the view (the ball representation), there is no 'game logic' for the ball (at the moment).

First to the model. The model needs data representing the various bits of the ball. This involves one new line, as we are doing it all in one go, in model.lua

function model.initialise()
model.bat = { x = 160, y = 440, width = 60 } 
model.bat.dx = 0 
model.bat.speed = 5
model.setBatDirection(1)
model.ball = { x = 100,y = 100, dx = 1,dy = 1,speed = 10, radius = 10 }
end

So our ball has a position, a vector, a speed, and a radius in the model.

Our view (in view.lua) needs to take this information and render it on the display. So we add this to the 'initialise' function, at the end

view.ballObject = display.newCircle(1,1,12) -- create a ball object (part 4)
view.ballObject:setFillColor( 0,1,1 ) -- make it cyan
view.ballObject.strokeWidth = 2
view.ballObject:setStrokeColor( 0,0,0 )
end

creating a circle with a border representing the ball. This means it is created when the view is initialised (if you were using composer it would create it response to the 'create' event)

In the update routine, it needs to update the relevant parts of the view from the model, i.e.

function view.update(model)
view.batObject.x = model.bat.x -- update the view from the model.
view.batObject.y = model.bat.y
view.batObject.width = model.bat.width

view.ballObject.x = model.ball.x -- update the ball (part 4)
view.ballObject.y = model.ball.y
view.ballObject.radius = model.ball.radius
end

Running this will give you an app that looks something like this. As with the last time, though I've added something.

The completed code for part 4 is at https://github.com/autismuk/MVP-Intro/tree/master/Part4

That's the exercise for today, add a score to the game.

Q: What do you add to the view and model ? What is the data that represents the score ? What is the visible thing that represents the score ? Where does each go ?

Q: What, if anything, happens in the presenter ?

A note on Physics

One of the problems with developing games using this structure, or similar structures, is that it is often running counter to the way Corona likes things - everything stuck together.

The Physics engine, for example, operates directly on the display objects, the view. This means that - pretty much - you can't use the Physics Engine a great deal.

One of the concepts of MVP, or indeed any system which separates the model and the view, is that you can replace the view with anything you like, pretty much. Suppose you wanted to have a vector representation, or a Retro look or whatever, or even display it on an external LED panel, you can do all these without changing anything other than a view. You could change it to a first perspective 3D game, and again, you'd change nothing other than the view.

Another advantage, especially if you use more Object Orientated programming, is that you can test things in isolation, even without any view at all. Everything isn't glued together.

It's really a case of pays your money and takes your choice :)

Saturday, 26 April 2014

Corona and the Model-View-Presenter pattern (Part 3)

In part 3, we are going to add the ability to control the paddle - it is a very simple control, it is going to reverse direction whenever you 'tap' on the bat. It's not the most exotic control system ever developed, but it shows the point.

In MVP the communication, whatever it is, between the model or view and the controller goes both ways.  So we need the 'view' to be able to send messages back to the 'presenter' - a "the bat's been tapped" message.

To do this, the view needs to know about the presenter, so it knows where to send the message. To do this, we have to make a little change to main.lua to allow the view to have a reference to the presenter.

model.initialise()  
view.initialise(presenter)
presenter.initialise()

at the same time, you can add the bit I forgot at the top to hide the status bar :)

display.setStatusBar( display.HiddenStatusBar )

We have added the presenter as a parameter to the initialisation code for the view, so the view will be changed (slightly) to support this. We also need to add an event listener for the bat object, so it picks up taps (note, the parameter list has changed as well as adding the two new lines)

function view.initialise(presenter)
    view.batObject = display.newRect(0,0,10,10)
    view.batObject:setFillColor( 1,1,0 )
    view.presenter = presenter
    view.batObject:addEventListener( "tap",view ) 
end

This stores the presenter in a variable called 'presenter', and creates a reference to a table listener event, that will call a function view.tap when it is tapped.

This function "sends a message" back to the presenter

function view:tap(e)
self.presenter.tapMessage()
end

It actually does this by calling a method 'tapMessage' rather than using listeners (aka the Observer pattern) - it calls a function in the presenter "tapMessage".

So those are all the changes to the view. It knows about the presenter, and it calls 'tapMessage' when it receives a tap.

Now, we need to make some changes to the presenter.

Another modification is for the update routine in the presenter to store a reference to the model, so it knows where the data is (otherwise the tapMessage function will not know which model to work on).

function presenter.update(model, view)
presenter.model = model
model.moveBat()
view.update(model)
end 

Last, we need to had a 'handler' for that 'message' (in practice, a function) which 'receives' the message and reverses the bat direction.

function presenter.tapMessage()
presenter.model.setBatDirection(-presenter.model.bat.dx)
end

When the tapMessage is received - in reality, the function is called, it sets the bat direction to the opposite bat direction.

I have mixed up access here, which is perhaps not ideal - in that the bat direction is read directly from the model but it is updated using a function. In good programming practice, you should really use accessors - setters and getters - for all the data, but this does create a lot of functions and can slow things down. It is a personal decision whether to access the model directly or via functions or not.

In the many years I have been programming - I started with one of these - I've seen so much code which was very well engineered but wouldn't actually work effectively on the hardware we had. Saying 'well, we can wait for faster computers' (yes, Gates, this means you) is not a good option.

You could also make a good case that there should be a function model.reverseDirection() which is called to do this. Again, there are no fixed rules - it is just one way of approaching it. This isn't a 'this is how you do it' - it is more 'this is a way of thinking about doing it'.

As long as you are consistent it doesn't matter. Generally, if it is likely to vary significantly - encapsulate it. In this particular case, writing presenter.model.bat.dx = -presenter.model.bat.dx would be okay.

So, it should now, when running, move the bat backwards and forwards, and when you touch it, or click it on the simulator, it should reverse direction.

It should look like this (Corona Simulator) ->

Exercise 1

... except, there'll be no bricks. It'll just be a black background.

I thought I should let you do some code of your own, rather than just following me, so the exercise for this 'lesson' is to put the background in.

Q: Where does it go ? Is it part of the view, model, or data ? Any or all of them ? Does it have associated 'game data' or 'game logic' ?

There is a working version in the repository at https://github.com/autismuk/MVP-Intro/tree/master/Part3 (which also has a brick graphic). Tiling an object in Corona isn't quite as easy as you might think :)

In part 4, I'll add a new view and model item - the ball.

Exercise 2 (Easy)

When running this I actually found it quite hard to click on the bat. How do you make the bat deeper (e.g. fatter vertically !) so it is easier to click ? Should this affect the view, or the model ? or the presenter ?

Corona and the Model-View-Presenter pattern (Part 2)

In this episode (?) we are going to get the bat moving at the bottom of the screen, and introduce the "presenter". The code in part 1 only had a view - the display bits and a model - the data bits, but no code to actually do anything.

This code will live in the presenter.

Please be aware this code is quite deliberately over engineered. In practice you wouldn't break it up quite as much as this - I'm trying to make it clear what is going on. Hence it does look a bit over the top at times, I'm writing far more code than I would normally.

What we want to do is to get the bat moving backwards and forwards on its own at the bottom of the screen. (in the game, we will touch the bat to make it change direction - okay, so Mass Effect III isn't under threat from this game ....)

So we need more things in the model. As well as its current 'data', the bat has a direction and a speed. So open model.lua and add the following code to model.initialise() (I will try to put 'old code' in italics throughout)

function model.initialise()
model.bat = { x = 160, y = 440, width = 60 } -- initialise the bat
model.bat.dx = 0 -- create model.bat.dx, model.bat.speed
model.bat.speed = 5  
model.setBatDirection(1)
end

We could, of course, just add dx = 0, speed = 5 to the model.bat "initialiser". We have a couple of 'helper functions' as well.

function model.setBatDirection(newdx)
model.bat.dx = newdx
end

function model.moveBat()
model.bat.x = model.bat.x + model.bat.dx * model.bat.speed -- move the bat.
if model.bat.x > display.contentWidth - model.bat.width/2 then -- check off the right
model.setBatDirection(-1)
end
if model.bat.x < model.bat.width/2 then -- check off the left.
model.setBatDirection(1)
end
end

You could put these in the presenter if you wanted - you could really lose 'setBatDirection' altogether and access the model directly. (This will really upset some OO fanatics ....)

There aren't really any fixed rules or anything about this - it depends how comfortable you are with whats going on, and how much you are likely to change the code in the future and where you think code belongs. These two functions are more about updating the model rather than game handling code itself, so they are better off in the model.

We don't change our view at all - it still looks the same. We do change the main program very slightly.

local model = require("model")
local view = require("view")
local presenter = require("presenter")

model.initialise()        -- initialise the model,view and presenter.
view.initialise()
presenter.initialise()

Runtime:addEventListener( "enterFrame", -- added code to update the presenter.
function(e) presenter.update(model,view) end)

Firstly we are now getting the presenter module - we didn't have it before, and it is being initialised. I have also removed the line that updates the view, it is the responsibility of the presenter to do this.

The last line causes the the presenter.update(model,view) line to be called on every frame (currently 30 times a second), so the presenter can keep updating the model, handling actions, updating the view etc etc.

Finally, and most importantly, we have the presenter. This is the code that actually "does stuff" and is all-new.

local presenter = { }

function presenter.initialise() -- our initialisation function does nothing.
end

function presenter.update(model, view)
model.moveBat()          -- move the bat.
view.update(model) -- update the view from the model
end

return presenter

Again, there is very little code here. We create a 'presenter' module, there is an initialise() function which does absolutely nothing at the moment, and our update routine, which is called at 30fps.

This does two things - it updates the model - moving the bat - and it then updates the view.

This is the big difference from Corona SDK in a nutshell. In Corona you'd just update the x position of the display object and it would move. The moveBat() call would do absolutely nothing to the visual part of the display - it just updates the data representing the display. The view won't update until you tell it to.

Now, you may well ask, what is the point of this ? What do you get by splitting it up ?

It's a bit of a balance - separating it allows you to easily change things without it having lots of knock on effects, and keep track of things more easily.

Against that, it takes more code, and more processor time to do it, and there is some duplication - x,y and width are kept in two separate places, both in the data model and the objects that make up the view.

Often the best approach can be a bit of a hybrid - so if your game as little bits of extras that aren't really part of the game - for example an explosion, then the view could handle this on its own - it's a graphic effect that doesn't effect the game core at all (in most games anyway !) - this sort of thing you learn by trial , error and experience. It makes changing things and fixing bugs easier - we will show this later on when we change a couple of things in the finished game.

Code for this part is at https://github.com/autismuk/MVP-Intro/tree/master/Part2

Note: someone asked me about Composer/StoryBoard (and Director, I guess ?), how does that fit in to this. Well, they are really part presenter and part model, but mostly view. Composer and the others handle different display sets at different times and transition between them.

However, they do have some concept of 'state' - where we are in the game process, and as ever with Corona SDK, the display objects have their own data as well. In a classical pattern, the data (x,y,rotate,xScale and so on) would belong in the model, the state (what current scene) in the presenter, and all the creating / eventing stuff in the view.

In the next episode, we will control the bat.