Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon

27. August 2012

 

A game isn’t much of a game if you can’t interact with it.  In this tutorial we are going to look at how to handle touch and click events with Moai.  This is however going to present a bit of a problem, you are going to need to have an Android or iOS device in order to test the touch events.  The code will still run in the Windows host, but you won’t be able to test touch events.

 

Speaking of the code:

 

screenWidth = MOAIEnvironment.screenWidth
screenHeight = MOAIEnvironment.screenHeight
print("Starting up on:" .. MOAIEnvironment.osBrand  .. " version:" .. MOAIEnvironment.osVersion)

if screenWidth == nil then screenWidth =640 end
if screenHeight == nil then screenHeight = 480 end

MOAISim.openWindow("Window",screenWidth,screenHeight)

viewport = MOAIViewport.new()
viewport:setSize(screenWidth,screenHeight)
viewport:setScale(screenWidth,screenHeight)

layer = MOAILayer2D.new()
layer:setViewport(viewport)

MOAIRenderMgr.pushRenderPass(layer)


sprite = MOAIGfxQuad2D.new()
sprite:setTexture("smile.png")
sprite:setRect(-200,-200,200,200)

prop = MOAIProp2D.new()
prop:setDeck(sprite)
prop:setLoc(0,0)
layer:insertProp(prop)

MOAIGfxDevice.setClearColor(1,1,1,1)

function handleClickOrTouch(x,y)
    prop:setLoc(layer:wndToWorld(x,y))
end


if MOAIInputMgr.device.pointer then
    MOAIInputMgr.device.mouseLeft:setCallback(
        function(isMouseDown)
            if(isMouseDown) then
                handleClickOrTouch(MOAIInputMgr.device.pointer:getLoc())
            end
            -- Do nothing on mouseUp
        end
    )
    MOAIInputMgr.device.mouseRight:setCallback(
        function(isMouseDown)
            if(isMouseDown) then
                MOAIGfxDevice.setClearColor(math.random(0,1),math.random(0,1),math.random(0,1),1)
            end
        end
    )
else
-- If it isn't a mouse, its a touch screen... or some really weird device.
    MOAIInputMgr.device.touch:setCallback (

        function ( eventType, idx, x, y, tapCount )
            if (tapCount > 1) then
                MOAIGfxDevice.setClearColor(math.random(0,1),math.random(0,1),math.random(0,1),1)
            elseif eventType == MOAITouchSensor.TOUCH_DOWN then
                handleClickOrTouch(x,y)
            end
        end
    )
end

 

Once again, we are building on our earlier example; and once again, we will not be covering those parts we already covered.  We are changing the functionality slightly.  Now in the event of a touch or left click, we are repositioning the happy sprite to the location the user clicked.  If the user double taps or right clicks, we change the background color… what can I say, not everyone loves white or hot pink. 

 

Here is the program in action:

image

 

 

Let’s take a look at the new code, starting from the top:

 

function handleClickOrTouch(x,y)
    prop:setLoc(layer:wndToWorld(x,y))
end

 

Touch and click events are two different events, but we want to share the same code when they happen, in this case a method called handleClickOrTouch.  It takes the x and y locations of the mouse cursor or finger that the touch/click happened at.  In the event of a touch, we simply want to move the happy face prop to the location of the touch.  First though, we need to translate the touch coordinates from window space to world space, which is accomplished with layer:wndToWorld().

 

if MOAIInputMgr.device.pointer then

MOAITInputMgr is a global object containing the various input devices that host platform supports.  Keep in mind, if your host does not support a given device, it will not exist in MOAIInputManager.  That is exactly what we are checking here, to see if device.pointer has been defined, which will only be defined if the host supports a mouse. 

 

The following types of input are *potentially* supported:

  • MOAIButtonSensor
  • MOAICompassSensor
  • MOAIJoystickSensor
  • MOAIKeyboardSensor
  • MOAILocationSensor
  • MOAIMotionSensor
  • MOAIPointerSensor
  • MOAITouchSensor
  • MOAIWheelSensor

 

The official documentation for MOAIInputMgr is completely empty, so if you are looking for more details, the course file MOAIInputMgr.cpp is perhaps your best source for more information.

 

Once we have determined that the host device does in fact support a mouse pointer, we run the following code:

    MOAIInputMgr.device.mouseLeft:setCallback(
        function(isMouseDown)
            if(isMouseDown) then
                handleClickOrTouch(MOAIInputMgr.device.pointer:getLoc())
            end
            -- Do nothing on mouseUp
        end
    )
    MOAIInputMgr.device.mouseRight:setCallback(
        function(isMouseDown)
            if(isMouseDown) then
                MOAIGfxDevice.setClearColor(math.random(0,1),math.random(0,1),math.random(0,1),1)
            end
        end
    )

 

First we register a callback function for mouseLeft, which takes a single bool parameter, indicating if the mouse button was pressed or released.  In the event that the mouse button was indeed pressed, we call the handleClickOrTouch function, passing in the mouse coordinates be obtain by calling MOAIInputMgr.device.pointer:getLoc().  We simply do nothing in the event of a mouse up, um.. event.

 

Next we register another callback, this time for the right mouse button.  In this case if the right mouse button was indeed pressed, we change the background to a random color.

 

So, that is what happens if we detected a mouse; if we don’t detect a mouse, we instead register a touch event handlers:

 

else
-- If it isn't a mouse, its a touch screen... or some really weird device.
    MOAIInputMgr.device.touch:setCallback (

        function ( eventType, idx, x, y, tapCount )
            if (tapCount > 1) then
                MOAIGfxDevice.setClearColor(math.random(0,1),math.random(0,1),math.random(0,1),1)
            elseif eventType == MOAITouchSensor.TOUCH_DOWN then
                handleClickOrTouch(x,y)
            end
        end
    )
end

 

While the left/rightButton event callbacks were passed a simple bool, the touch callback get’s a fair bit more information.  The following values are passed to the touch callback function:

eventType: The type of event that occurred. The value will be either TOUCH_UP or TOUCH_DOWN

idx: It touch index in case multiple simultaneous touches occurred

x: The x coordinates of where the touch happened on screen

y: The y coordinates of where the touch happened on screen

tapCount: the number of taps that occurred 

 

In the event that multiple taps occurred, we change the window background color to a random RGB value.  Otherwise, it was a single touch, in which case we call handleClicksOrTouch passing in the x,y value passed in the touch callback.

 

The parameters for the touch callback function were also not documented, so it took a little bit of digging to divine exactly what they are.  If you are interested, the actual code for setting the parameters is in the method MOAITouchSensor::HandleEvent, in the file MOAITouchSensor.cpp

 

Now we have the ability to be all touchy feely, we are yet another step further along in our adventures in Moai-land.  Stay tuned for the next exciting episode where we journey even deeper!  There may even be a prize at the end(*)!!!

 

 

(*) – the prize is a lie.

 

 

 

 

 

Programming , ,

27. August 2012

 

As the title suggests, Blitz Basic Plus is currently free right now, marked down from the regular price of 60$.  bbasiclogo

 

Blitz Basic, in their own words, is:

BlitzPlus provides developers with a complete 2D programming solution for the PC. Utilising a BASIC/C hybrid language for use with its compiler, BlitzPlus is capable of creating any type of 2D program, with minimal development-time and with minimal hassle. Just run the included IDE (or use one of your own), type your code and your Windows executable file will be created, ready to be run on any computer running Windows 95/NT 4 or later.

 

While the Blitz Basic language is:

 

BlitzPlus' language is a BASIC/C hybrid. As well featuring the classic BASIC constructs such as goto and gosub, it also features C influences such as functions and types. On top of this, BlitzPlus' command set features over 500 commands. This command set is highly streamlined meaning complete programs require very few lines of code indeed.

 

Apparently the original Worms was developed in BlitzBasic, as was the Eschalon RPG series.  I personally have never tried Blitz and don’t really intend to as I have never really been a fan of BASIC, but it is certainly worth checking out, especially for the price of 0$.

 

You can purchase it here.  I have no idea how long the offer is on for.

News

25. August 2012

 

This is a general list of the various resources, books, tutorials and forums available for learning and working with Moai and Lua.  I will keep updating it as I discover more resources.  If I made a mistake or omission, please let me know either in comments or via the Contact form.

 

Books

 

 

Books on Safari

 

 

 

Key websites

 

General ,

24. August 2012

 

So, it might be obvious by the fact the last five posts have all been Moai related…  Well, I have embarked on a Moai tutorial series.

 

This series is meant to make the very professional oriented Moai SDK more accessible to all developers.  There isn’t a glut of information out there, so I have decided to create this tutorial series.  It is *very* conversational and if you have prior game programming experience you may roll your eyes at some of the detail I go into.  If you are new though, hopefully this information is a godsend.

 

 

Anyways, as you can see if you look below this post, there are 4 posts already.  One on setting up the IDE, a simple hello world/setup post, then two “official” tutorials, one on creating a window/app and one on displaying a sprite.  More of course are coming soon.

 

 

Here then is the table of contents.  I will add it to the main navigation of this site shortly.

 

Enjoy, and of course, feedback always appreciated.

News , ,

24. August 2012

 

When we last visited Moai land things were getting started, hot and pink; but just a bit boring.  Let’s spice it up a bit with a sprite that totally isn’t the logo from Watchmen!

 

screenWidth = MOAIEnvironment.screenWidth
screenHeight = MOAIEnvironment.screenHeight
print("Starting up on:" .. MOAIEnvironment.osBrand  .. " version:" .. MOAIEnvironment.osVersion)

if screenWidth == nil then screenWidth =640 end
if screenHeight == nil then screenHeight = 480 end

MOAISim.openWindow("Window",screenWidth,screenHeight)

viewport = MOAIViewport.new()
viewport:setSize(screenWidth,screenHeight)
viewport:setScale(screenWidth,screenHeight)

layer = MOAILayer2D.new()
layer:setViewport(viewport)

MOAIRenderMgr.pushRenderPass(layer)

sprite = MOAIGfxQuad2D.new()
sprite:setTexture("smile.png")
sprite:setRect(-200,-200,200,200)

prop = MOAIProp2D.new()
prop:setDeck(sprite)
prop:setLoc(0,0)
layer:insertProp(prop)

MOAIGfxDevice.setClearColor(1,1,1,1)

 

And when you run it:

 

image

 

At least half of this code we covered in the prior tutorial, so we will skip right past that and jump in to what’s new:

 

sprite = MOAIGfxQuad2D.new()
sprite:setTexture("smile.png")
sprite:setRect(-200,-200,200,200)

 

Our “sprite” is in fact a MOAIGfxQuad2D, which may at first sound like a remarkably more confusing name than sprite.  You see, behind the scenes Moai ( and pretty much every other modern engine ) is actually working in 3D, not 2D.  It’s just the way GPUs work these days.  So when you see a 2D library, it is actually faking 2D by creating a 3D scene and ignoring one of the D’s.  As part of the process, you don’t really have sprites anymore, instead you have textured quad’s ( 4 vertices rectangles ) that are parallel to the camera.  So, we create a rectangle that is aligned to the camera and draw our texture on top of it, giving the illusion of being a simple sprite or image, but making the GPU happy at the same time.  So… that’s why it’s called a MOAIGfxQuad2D instead of say… a sprite.

 

Anyways, we create a new MOAIGFXQuad2D, and set it’s texture to the file name we want to load onto it.  Oh yeah, you need an image to display, and you need to copy it to the same folder as main.lua.  While we are on the topic of “oh yeahs!'”, save the above code to a file named main.lua!  Once we load our texture, we are going to size and position our quad in a single call, setRect().  Coordinates are relative to the center of the screen, so position 0,0 is exactly in the middle of your screen.  So when we say –200,-200, we are saying the top left corner of the rectangle is 200 pixels to the left of center and 200 pixels above center.  While the other 200,200 is saying the bottom right corner of the quad is 200 pixels to the right and 200 pixels down from the center point.  End result, we create a textured quad centered to our screen that is 400x400 pixels, so I suppose that is technically a square.  By changing the values in setRect, you can reposition the sprite ( for example (-400,-200,0,-200) would move the quad 200 pixels to the left ) as well as scale it ( (-100,-100,100,100) would scale it to half it’s current size ).

 

prop = MOAIProp2D.new()
prop:setDeck(sprite)
prop:setLoc(0,0)
layer:insertProp(prop)

Now we create a MOAIProp2D.  Remember in the last tutorial when I said layers are made up of stuff that are composed together to create the frame?  Well a MOAIProp2D is one such example of “stuff”.  What then does setDeck do?  In the simplest term, think of a “Deck” as a data source.  An image or a sprite sheet ( or texture atlas in Moai parlance ) are both examples of decks.  Think of a Prop is an *instance* of a deck, or perhaps most accurately instanced from a deck.  To make life easier on yourself, just think of a deck as the data source for a prop.  I’ll be honest, I'm not a huge fan of the metaphor they choose, but then if you read their explanation, neither are they.  Next you position the prop within the layer, keeping in mind 0,0 is dead center.  Finally, the prop is inserted into the layer via insertProp(). To finish things off:

 

MOAIGfxDevice.setClearColor(1,1,1,1)

 

I like pink as much as the next man, but sometimes I like white a whole lot more.

 

That, is how you display a sprite ( erm, Prop ) on screen.

 

But wait!  There’s more…

 

You do however have a couple options.  You see, loading from file can be a bit expensive, especially if you are using the same image over and over.  So, instead of loading the sprite from disk in the setTexture call, lets instead load it from an Image already loaded and resident in memory.

 

texture = MOAIImage.new()
texture:load("smile.png")

sprite = MOAIGfxQuad2D.new()
sprite:setTexture(texture)
sprite:setRect(-200,-200,200,200)

 

Here we create a MAOIImage in advance, load the image file into it, then use that in our setTexture() call.  Now instead of loading from disk, it loads from memory, which is substantially quicker.  One thing should be pointed out here, that image is in system memory and needs to be copied to the GPU each time it is drawn.  Don’t worry, this makes sense and is completely normal, but on occasion can be a bit hard on performance.  If you have an image that is drawn a lot, like say, the player sprite or a static part of the HUD, you may want to cut the whole copy to video memory out of the equation and store your sprite in video memory.  MOAI has a way to do this as well.

 

texture = MOAIImageTexture.new()
texture:load("smile.png")

 

Basically you just use MOAIImageTexture instead of MOAIImage.  Keep in mind, video memory is a constrained resource, so don’t do this lightly.  Also keep in mind, changing the item in video memory effectively ruins any point of it being there in the first place, so only use MOAIImageTexture if your image isn’t changing often.  I would generally recommend you go with normal MOAIImage until you have a good reason not to.  Be careful, your optimization can easily cause performance to get worse!

 

 

And done…  you now know how to draw an image on screen, one step closer in our master plan to take over the wor… er, create a game.  Stay tuned for the next exciting episode where we demonstrate how to successfully raise a peasant army… or handle touch events.  One of those two topics, I’m not sure which yet.

 

Programming , ,

Month List

Popular Comments

RPG Maker and Spriter both massively discounted today on Steam
Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon


Home > News >

27. May 2015

 

So today I fired up Steam to finally pull the trigger on Pillars of Eternity and what do I see….

 

image

It seems that Degica games, the makers of the popular RPG Maker series of game building tools are having a sale today.  Their flagship product RPG Maker VX Ace ( … quite the name ) is currently on sale for 80% off.

 

On top of RPG Maker Vx Ace, RPG Maker XP and RPG Maker 2003 are all also discounted, 80% and 50% respectively.  What perhaps caught my eye most of all however wasn’t the RPG Maker line of products, but Spriter is also on sale for 75% off.   Spriter was a successfully kickstarted project made by BrashMonkey, I had no idea Degica was now the publisher.

 

About Each Program

 


RPG Maker

 

 

This is a program that has been around for a very long time, first released in 1988.  As the title suggests, it’s a game building tool for making RPG’s, generally of the classic jRPG format.

 

That said, this is a proper game building application, a number of commercially shipped games were created using the various iterations of RPG Maker.  RPG Maker was mentioned as an option in my guide to getting kids started in game development.  Bundled with a ton of premade assets, it is a good way to get your hands wet in game development.  In addition to world, character, dialog, etc… building tools, there is also a programmatic layer using the Ruby programming language. 

 


Spriter

 

Perhaps of most interest to GameFromScratch readers is Spriter.  Spriter is essentially a modular 2D animation system.  You basically cut your sprites up into multiple independent pieces which in turn can be animated.  You can also apply an IK chain ( inverse kinematics… think skeleton ) that controls the animation for you.  You can then export the resulting animation as a sprite sheet, sequence of images or as an animated gif.

 

Most likely though you will want to use the Spriter API, or one of the pre-existing plugins, and use the Spriter animations directly in your game engine, such as Construct, Unity or LibGDX.

 

Truth is, I did a pretty lousy job there describing Spriter, so I will just show their video instead…

 

 

Both are on sale until May the 29th. 

 

Oh, and as I finish typing this up, the Steam page for the sale now appears to be broken…

News ,

blog comments powered by Disqus

Month List

Popular Comments