Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon
19. September 2012

The ignore me part of this post is very real, this post has content that is probably of very little interest to 99% of you.  You see, until now I have been spoiled by the wonderful ( and free! ) Windows Live Writer blogging software, part of the Windows Live Essentials package.  Coincidentally that pack also includes a very good video editing package, so if you have written it off as garbage, you've made a serious mistake.

 

 

Anyways, Windows Live Writer seems to be universally regarded as the best blogging software out there ( Google it… this shocked me too! ), and on a Mac there is no good (free) alternative.  There is however hope, in the form of MarsEdit which I am currently giving a test drive in this post.  It's 40$, which compared to free is quite expensive, but compared to say…  kobe beef, is extremely cheap.  It's quite simple initially, but seems to do most of what I require so far…  mind you, I haven't posted any images or source code yet, so who knows what is going to happen.  I also haven't tried editing an existing post ( too afraid ), or editing a MarsEdit post in WLW ( I haven't got one yet. )

 

So that is what this post is all about… test driving MarsEdit and then seeing how friendly it plays with Windows.  So, the rest of this post is going to be a mish-mash of … stuff.

 

So, feel free to ignore me :)  Unless of course, you too recently added a Mac to your daily regime and are looking for a blogging alternative to Live Writer.  Oh, and I tried QTM already ( it was free ), and…  yeah, no.

 

The good news so far is, it spoke to my blog, got all the recent posts and downloaded the categories, which is nice as I use a slightly less common blog platform ( BlogEngine ).  That said, I haven't seen support for tags yet...

 

Now lets give an image a shot.

 

This is a centre aligned image ( of Oolong, the famous pancake balancing rabbit.  It appears you can position easily enough, but image effects and wrapping text

Oolong

around the image is beyond MarsEdit.

 

Now lets see what happens with a right aligned image, If this text can't be wrapped around an image, that is actually a gigantic deal breaker right there.

Oolong

 

Hmm, well it appears I can at least do that much, but I don't appear to be able to set the padding between my text and the image.

 

 

Perhaps even more oddly, I don't have the ability to resize an image once it has been added.

 

That frankly is just bizarre.

 

Also, I am just typing this stuff so I can fill the space to the bottom of the image.  Not that I can guarantee that will make sense once published, as this column of text doesn't come close to matching the actual width of my blog, so I have no idea how the text is going to format once posted.

 

Now it's time to see how code gets pasted:

 

var express = require('express'),
server = express.createServer();

server.use('/scripts', express.static(__dirname + '/scripts'));

server.get('/', function (req, res) {
res.sendfile('index.html');
});

//server.get('*', function (req, res) {
// res.redirect('/#' + req.url, 302);
//});

server.listen(process.env.PORT || 3000);

 

Hm, default from WebStorm, it pastes as simple text.  Well, that's not going to work.  There doesn't appear to be any plugin support, so let's try pasting as RTF from the wonderful Sublime Text:

 

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

 

 

Hmmm, nope.  HTML maybe?

 

viewport = MOAIViewport.new()

viewport:setSize(screenWidth,screenHeight)

viewport:setScale(screenWidth,screenHeight)

 

main.lua

09/19/12 10:04:21 /Users/Mike/Dropbox/Moai/Adventure/2/main.lua
  5
if screenWidth == nil then screenWidth =640 end
  6
if screenHeight == nil then screenHeight = 480 end
  7  
  8
MOAISim.openWindow("Window",screenWidth,screenHeight)
  9  
10
viewport = MOAIViewport.new()
11
viewport:setSize(screenWidth,screenHeight)
12
viewport:setScale(screenWidth,screenHeight)

 

 

 

… well, getting there, but ugly as sin.  Thats using the ExportHtml plugin for Sublime Text.  I will look in to a better option in the future.

 

EDIT: Opened and edited in MarsEdit.  No tag support, picture formatting is meh at best and I am not happy with code markup yet, but the basics are there for now.  May have made progress with code formatting:

 

09/19/12 10:26:20 /Users/Mike/Dropbox/Moai/Adventure/2/main.lua 
17 MOAIRenderMgr.pushRenderPass(layer)
18
19 sprite = MOAIGfxQuad2D.new()
20 sprite:setTexture("smile.png")
21 sprite:setRect(-200,-200,200,200)
layer = MOAILayer2D.new()
layer:setViewport(viewport)
 
MOAIRenderMgr.pushRenderPass(layer)
 
sprite = MOAIGfxQuad2D.new()
sprite:setTexture("smile.png")

sprite:setRect(-200,-200,200,200)

EDIT2: Pages opens and edits fine in Live Writer.

 

 

Verdict:

 

MarsEdit may work for me, but the lack of built in code formatting makes things a gigantic pain in the hoop, as do the lack of image formatting tools and (albeit a minor point) the lack of tagging.  On the other hand, I really do like the editing environment, it’s a much nicer and more natural experience than Live Writer.  The publishing process is also much nicer, as is the management aspects.

 

On the whole, MarsEdit seems like a capable product that falls short in a few key categories.  If I find nothing else, I will probably purchase a license.  Does anyone have another recommendation for Mac based blogging software?z

Totally Off Topic


18. September 2012

 

I just read on Reddit  that Meridian 59 has been open sourced and hosted on Github.  I took a quick look at the code and it was written in straight C and appears to be quite clean and easy to read, at least, as readable as Win32 C code can be!

 

If you have never heard of Meridian59, it was one of the first MMORPG’s that was published by the now defunct 3D0 Company.  In fact, it was the first commercial 3D MMO released.  The company that developed it went under, then another company went took over and later went under as well.  However they have managed to keep the servers running in a non-commercial capacity and people are still playing to this very day.  Always awesome to see people release commercial source code, even slightly older code.  There aren’t too many MMO’s open sourced.

 

Getting it to build might be a bit of a trick though.  Parts haven’t been open sourced, specifically the compression library and audio library, although I believe they are provided in binary form.

 

Perhaps the biggest gotcha is going to be building the room editor, which requires Borland 4.5!!! to build.  Ironically I think I have a copy on disk somewhere, as Borland C++ was the compiler of choice when I was in University.  The remaining code compiles with Visual Studio 2008.

 

So, if you ever wanted to peek behind the curtain on a commercial MMO, here’s your chance!

News


18. September 2012

 

The release candidate for the upcoming Blender 2.64 release was um, released today ( that’s a lot of releasing… ).blenderSS

 

For game developers, there isn’t really a ton in this release targeting you, but then, we made out like bandits in the prior release so we can’t be greedy I suppose.

 

Of perhaps most interest to game developers, are the following features:

 

Mesh Tools

Bevel and inset now are modal operator with mouse control, a wire frame tool was added to turn edges into wireframe tubes, and vertex/edge/face sorting tools were improved.

 

Sculpting

Sculpting has received some major improvements such has masking to control which areas of the mesh are influenced by sculpting, new brush map modes to control how textures are projected onto the model, and an input stroke averaging option to make brush strokes smoother.

 

Skin modifier

The Skin modifier takes a skeleton made up of vertices and edges as input and generates a polygon skin as output, consisting mostly of quads aligned along the edges. The output is mostly quads, although some triangles will appear around intersections.

 

Game Engine

Lamps and shadows were improved with support for variance shadow maps, shadow color, sun lamp shadows and lamp textures. Non-power of two textures and compressed textures will now load faster and use less memory. A new Character physics type was added, designed for player controlled characters for which a full dynamics simulation would give unwanted behavior.

 

and perhaps most important of all:

Collada

The Collada exporter has been improved for better support of export to game engines, with more fine grained options to control which data is exported.

 

In addition to the above changes, there were a number of changes to the camera tracking tool, the Cycles renderer, green screening tools and a number of smaller fixes and tweaks.

 

You can download the release candidate here.

Art


17. September 2012

 

In this tutorial, we are going to look at how to play audio using Moai.  This is going to make heavy use of moaigui, so if you haven’t already, you may want to check the prior tutorial in this series.

 

As always, let’s jump right in to the code.  You may notice that the code order is starting to seem a little… odd. This is because I am grouping code mostly in order of newness, as opposed to how it would logically be laid out.  If you are thinking “I wouldn’t order things this way!”, well.. neither would I, normally.

 

screenWidth = MOAIEnvironment.screenWidth
screenHeight = MOAIEnvironment.screenHeight
if screenWidth == nil then screenWidth =1280 end
if screenHeight == nil then screenHeight = 800 end


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

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

package.path = './moaigui/?.lua;' .. package.path
require "gui/support/class"
local moaigui = require "gui/gui"
local resources = require "gui/support/resources"
local filesystem = require "gui/support/filesystem"
local inputconstants = require "gui/support/inputconstants"
local layermgr = require "layermgr"


local gui = moaigui.GUI(screenWidth,screenHeight)


gui:addToResourcePath(filesystem.pathJoin("moaigui/resources", "fonts"))
gui:addToResourcePath(filesystem.pathJoin("moaigui/resources", "gui"))
gui:addToResourcePath(filesystem.pathJoin("moaigui/resources", "media"))
gui:addToResourcePath(filesystem.pathJoin("moaigui/resources", "themes"))

layermgr.addLayer("gui",99999, gui:layer())
gui:setTheme("basetheme.lua")
gui:setCurrTextStyle("default")

function onPointerEvent(x, y)
    gui:injectMouseMove(x, y)
end

function onMouseLeftEvent(down)
    if(down) then
        gui:injectMouseButtonDown(inputconstants.LEFT_MOUSE_BUTTON)
    else
        gui:injectMouseButtonUp(inputconstants.LEFT_MOUSE_BUTTON)
    end
end

function onTouchEvent(eventType,idx,x,y,tapCount)
    --gui:injectTouch(eventType,idx,x,y,tapCount)
    onPointerEvent(x, y)
    if (MOAITouchSensor.TOUCH_DOWN == eventType) then
        onMouseLeftEvent(true)
    elseif (MOAITouchSensor.TOUCH_UP == eventType) then
        onMouseLeftEvent(false)
    end
end


if MOAIInputMgr.device.pointer then
    MOAIInputMgr.device.pointer:setCallback(onPointerEvent)
    MOAIInputMgr.device.mouseLeft:setCallback(onMouseLeftEvent)
else
    MOAIInputMgr.device.touch:setCallback(onTouchEvent)
end


function onButtonClick(event,data)
    if(string.find(buttonPlay:getText(),"Play") ==1) then
        song1:play()
        buttonPlay:setText("Stop, that's creeping me out!")

        function checkSongDone()
            local song = song1
            while song1:isPlaying() do coroutine:yield() end

            song1:stop()
            buttonPlay:setText("Play Audio File using Untz")
        end

        if not checkLoop:getChecked() then
            songPlayingThread = MOAICoroutine.new()
            songPlayingThread:run(checkSongDone)
        end
    else
        song1:stop()
        buttonPlay:setText("Play Audio File using Untz")
    end
end

function onButtonRewind(event,data)
    if song1:isPlaying() then
        local pos = song1:getPosition()
        local length = song1:getLength()
        local tenPercent = (length * 1.10) - length
        pos = pos - tenPercent
        if(pos > 0) then
            song1:setPosition(pos)
        end
    end
end

function onButtonFastForward(event,data)
    if song1:isPlaying() then
        local pos = song1:getPosition()
        local length = song1:getLength()
        local tenPercent = (length * 1.10) - length
        pos = pos + tenPercent
        if(pos < length) then
            song1:setPosition(pos)
        end
    end
end

function onCheckboxChanged()
    song1:setLooping(checkLoop:getChecked())
end

function onVolumeChanged()
    MOAIUntzSystem.setVolume(sliderVolume:getCurrValue() / 100)
end



buttonPlay = gui:createButton()
buttonPlay:setPos(0,0)
buttonPlay:setDim(100,25)
buttonPlay:setText("Play Audio File using Untz")
buttonPlay:registerEventHandler(buttonPlay.EVENT_BUTTON_CLICK,nil,onButtonClick)

checkLoop = gui:createCheckBox()
checkLoop:setPos(0,26)
checkLoop:setDim(100,10)
checkLoop:setText("Loop?")
checkLoop:registerEventHandler(checkLoop.EVENT_CHECK_BOX_STATE_CHANGE,nil,onCheckboxChanged)

labelVolume = gui:createLabel()
labelVolume:setText("Volume")
labelVolume:setPos(0,36)
labelVolume:setDim(30,10)

sliderVolume = gui:createHorzSlider()
sliderVolume:setPos(30,36)
sliderVolume:setDim(70,10)
sliderVolume:setRange(0,100)
sliderVolume:setCurrValue(50)
sliderVolume:setValueDisplayLoc(sliderVolume.VALUE_DISPLAY_RIGHT)
sliderVolume:registerEventHandler(sliderVolume.EVENT_SLIDER_VALUE_CHANGED,nil,onVolumeChanged)

buttonRewind = gui:createButton()
buttonRewind:setPos(0,50)
buttonRewind:setDim(50,10)
buttonRewind:setText("Rewind")
buttonRewind:registerEventHandler(buttonRewind.EVENT_BUTTON_CLICK,nil,onButtonRewind)

buttonFastForward = gui:createButton()
buttonFastForward:setPos(51,50)
buttonFastForward:setDim(50,10)
buttonFastForward:setText("Fast Forward")
buttonFastForward:registerEventHandler(buttonFastForward.EVENT_BUTTON_CLICK,nil,onButtonFastForward)

MOAIUntzSystem.initialize ()
MOAIUntzSystem.setVolume(0.5)
song1 = MOAIUntzSound.new()
song1:load("demongirls.ogg")

 

If we run the application( in the Moai-untz host ), we see:

 

image

 

Click the “Play Audio File using Untz” button and the song will play, the slider increases and decreases the volume, the loop check box I bet you can guess what it does.  Rewind and Fast Forward change the playback position by 10% at a time.

 

This looks like a wall of code, but don’t worry, it’s not all that bad.  In reality, most of it is maoigui code that we covered earlier.  We use a couple of new controls ( the check box and slider ), but nothing in the UI code should be all together new.  Most of our new logic is in the click handler methods, so let’s start there.

 

function onButtonClick(event,data)
    if(string.find(buttonPlay:getText(),"Play") ==1) then
        song1:play()
        buttonPlay:setText("Stop, that's creeping me out!")

        function checkSongDone()
            local song = song1
            while song1:isPlaying() do coroutine:yield() end

            song1:stop()
            buttonPlay:setText("Play Audio File using Untz")
        end

        if not checkLoop:getChecked() then
            songPlayingThread = MOAICoroutine.new()
            songPlayingThread:run(checkSongDone)
        end
    else
        song1:stop()
        buttonPlay:setText("Play Audio File using Untz")
    end
end

This is the code that is executed if the brilliantly named buttonPlay button is clicked.  The first thing we do is check to see if the button’s text starts with “Play”, which if it does, that means we are currently not playing a song.  Therefore we start playing our song ( aptly named song1 ) with a call to the play() method.  We then update our button’s text to indicate it’s new status.  The next little bit of code might seem a bit confusing at first, but it is pretty powerful.

 

First we are declaring a nested function checkSongDone().  The next line is where the magic happens.  It’s a while loop that loops until the condition isPlaying() becomes false.  Each pass through the loop we call coroutine:yield().  So, what the heck was that all about? Well… this is going to be a bit tricky to explain, but I will do my best.

 

If you are an old fart like me, you may remember multitasking in the pre-Win95 pre-emptive multitasking days.  Essentially you ran multiple programs at the same time by giving each one a chunk of processing time and a well behaved program was supposed to yield control when it wasn’t busy.  Essentially the operating system switched between running programs and said “ok, your turn” and a well behaved program would quickly exit if it was done doing whatever it needed to do.  Well, in a nutshell that is what is happening here.

 

A coroutine is sort of the Moai version of a thread.  Using coroutines, you are able to run code in parallel, so while our game loop is still running, the function checkSongDone is blissfully churning away in the background checking to see if the song is done.  Thing is, until the song is actually done, the coroutine doesn’t really have anything else to do, so it calls yield().  It is not until that condition is true ( isSongPlaying returns false ) will the function continue execution.  Once this happens we (somewhat redundantly) call song1:stop() then update the button’s text to “Play Audio…”.  The end result of this whole chunk of code is, we essentially created an on song end handler, so when the song is done playing, the text of the button will update.

 

The next chunk of code checks the checkbox checkLoop, which if checked indicates that we want the song to loop continuously.  If it is not checked, that means we want to run our coroutine, which we create with a call to MOAICoroutine.new(), then run with the run() method, passing in the function to run.

 

If the button’s text however indicates that the song is playing, in which case the button acts like a STOP button, simply stopping playback ( even if loop is checked ) and resetting back to the “Play…” text.  I encourage you to look deeper in to Coroutines, they are a very powerful feature of Lua. MOAICoroutine itself is only a thin wrapper over Lua’s coroutine abilities.

 

Also, you may have noticed MOAIThread in the examples and wondered when to using MOAIThread instead of MOAICoroutine.  The short answer is, you dont!  The more accurate and useful short answer is, MOAIThread *IS* MOAICoroutine.  It was renamed and the documentation just hasn’t caught up yet.  Well at least, it hadn’t at the point I wrote this.

 

TL;DR, coroutines are cool, learn about them, use them, love them.

 

function onButtonRewind(event,data)
    if song1:isPlaying() then
        local pos = song1:getPosition()
        local length = song1:getLength()
        local tenPercent = (length * 1.10) - length
        pos = pos - tenPercent
        if(pos > 0) then
            song1:setPosition(pos)
        end
    end
end

function onButtonFastForward(event,data)
    if song1:isPlaying() then
        local pos = song1:getPosition()
        local length = song1:getLength()
        local tenPercent = (length * 1.10) - length
        pos = pos + tenPercent
        if(pos < length) then
            song1:setPosition(pos)
        end
    end
end

This is the code that executes if you hit the Fast Forward or Rewind buttons.  Basically it gets the current position of the song ( playback-wise ) using getPosition() and the length of the song using getLength().  Next we calculate what 10% of the length is, and either add or subtract that amount from the current position depending if we are fast forwarding or rewinding.  Next we check sure to make sure the position is valid after being modified and if it is, we change the position of the song using setPosition().  End result, pressing Fast forward advances the song by 10% of it’s length, while hitting rewind moves it back 10%.

 

function onCheckboxChanged()
    song1:setLooping(checkLoop:getChecked())
end

This is the code that executes if the checkbox checkLoop is checked or unchecked.  It simply toggles the value of setLooping based off the if the checkbox is checked, using getChecked().

 

function onVolumeChanged()
    MOAIUntzSystem.setVolume(sliderVolume:getCurrValue() / 100)
end

This is the code that is executed if the slider sliderVolume is changed.  This uses the MOAIUntzSystem singleton to change the global volume level using setVolume().  setVolume takes a value from 0.0 to 1.0, while the sliders value returned by getCurrValue() is from 0 to 100, so we divide it by 100.

 

So then, what the heck is an Untz?  It’s the included cross platform audio system.  You also have the option to use FMOD, a commercial audio solution.  Untz does the trick though, works on Android and iOS.  There is a very important caveat… if you are going to be running using the UNTZ audio library you need to use the Moai-untz host!!! when running on the PC.  You will get exceptions if you try to call MOAIUntzSystem from the normal Moai host.  The Moai-untz host is in the same directory as the Moai host.

 

Most of the UI code is pretty much identical to what you’ve seen already, so I wont really go into it, that leaves:

 

MOAIUntzSystem.initialize ()
MOAIUntzSystem.setVolume(0.5)
song1 = MOAIUntzSound.new()
song1:load("demongirls.ogg")

This code first initializes the MOAIUntzSystem singleton.  Then it sets the global volume to 50%.  Next we create our song song1 with a call to MOAIUntzSound.new().  Finally load the song ( in the same directory as main.lua ) with a call to load().

 

You might be asking yourself “what sound formats does Untz support?”.  That’s a good question with a tricky answer.  Basically the safe answer is ogg and wav.  The not so safe answer is, it depends on the platform.  For example, iOS, Mac and Windows will work with mp3, but Android wont.  Beyond WAV and OGG, the file is just passed to the native system for handling, so if the platform supports it, Moai supports it.

 

But if you really want to be cross platform, just encode everything in to ogg.  In this day of increasingly wealthy lawyers, the last thing we want to do is deal with a patent encumbered format like mp3!

 

Oh yeah, and the music… it’s seriously creepy stuff and I downloaded it from here.  Obviously you can substitute any song you want from your Justin Beiber collection, just make sure it’s not an MP3 if you are running on Android.  Of course, you can convert from just about any audio format to just about any other audio format using the free and amazing Audacity.  I do get 10% of all proceeds for saying that.  I may need a new business model.

 

Programming


17. September 2012

In recent years I have gotten used to having increasingly larger hard drives, so I never really paid attention to how large Windows 7 had gotten.  Until I recently installed Win 7 on a 60GB SSD partition…

and nearly half of if was consumed by the OS!

 

This is simply put, insane.

 

The first obvious use of space is the PageFile ( 4GB, or 1 to 1 with actual RAM ), but for now I am leaving that one be.  So I wondered how much low hanging fruit I could get, and the answer is, surprisingly a lot.

 

First to go, System Restore.  I never use this feature anyways.  I backup remotely, so If my OS corrupts, I reinstall.  I never trust the state of a machine that requires a System Restore anyways.  Net savings, 1.5GB.

 

Next up, and this one kinda sucks to remove, but Hibernate.  Removing Hibernate ( powercfg –hibernate off ).  Net savings, 4GB.

 

Then I went in to Windows Features and removed the bits I didn’t use ( Games, DVD Maker, a few others ) for a grand total savings of a few hundred MB.  Meh.

 

At this point I started to think I was out of options, then I looked at WinSxS in the Windows folder… holy crap.

 

image

 

10GB, and a fresh install!  What the hell is going on here!

 

So looking in to it a little deeper, apparently Windows 7 makes a backup copy of pretty much every file it ever patches, so after a service pack there is a gigantic amount of bloat, so you can uninstall the Service Pack.  This one falls under the same category as System Restore… I will not undo a Service Pack install… I will reinstall completely.  Problem is, I couldn’t figure out a way to remove bits from WinSxS safely, until I found this.

Basically you run ( as Admin )

dism /online /cleanup-image /spsuperseded

and:

image

 

And after it finished:

 

image

 

A net savings of nearly 4GB. 

 

So, grand total I managed to shrink the install size down by damn near 50%, with almost no downsides.  So, if you are running on a solid state drive and need more space free, consider the steps above.  Just a warning, if something goes wrong ( a bad driver install, a corrupted program install, etc… ) you will probably be doing a reinstall.

Totally Off Topic


See More Tutorials on DevGa.me!

Month List