Thursday, October 29, 2015

E-Mail Merge in Go

Mail merge is a funny thing.  Once a year, I use "mail merge" in Microsoft Office to produce envelopes that are physically mailed.  Mail merge is really good for that... you can make a single word doc that is easy to print, and then you've got all the physical documents you need, ready to be taken to a physical post office.

As a professor, there are many, many times that I need to do a mail merge that results in an email being sent.  Partly because I do a lot of work in Linux environments, and partly because of other oddities of how I like to work, I usually have a hybrid Excel-then-text workflow for this task.

The first step is to produce a spreadsheet, where each column corresponds to the content I want placed into an email.  Ultimately, I save this as a '.csv' file.  Importantly, I make sure that each column corresponds to text that requires no further edits.  If I'm sending out grades, I'll store three columns: your sum, the total, and your average.  You could imagine something like the following:
bob@phonyemail, 15, 20, 75% 
sue@phonyemail, 19, 20, 95%
...
The third step (yes, I know this sounds like Underpants Gnomes) is that I have one file per email, saved with a name corresponding to the email address, ready to be sent, and I use a quick shell script like this to send the files:


for f in *; do mutt -s "Grade Report" -c myemail@phony.net $f < $f; done


That is "for each file, where the name happens to be the same as the full email address of the recipient, send an email with the subject 'Grade Report', cc'd to me, to the person, and use the content of the corresponding file as the content of the email".

So far, so good, right?  What about phase two?  I'm pretty good with recording emacs macros on the fly, so I used to just record a macro of me turning a single line of csv into a file, and then replay that macro for each line of the csv.  It worked, it took about 10 minutes, but it was ugly and error-prone.

I recently decided to start learning Google Go (in part because one of the founders of a really cool startup called Loopd pointed out that native code performance can make a huge difference when you're doing real-time analytics on your web server).  Since I've simplified my problem tremendously (remember: the csv has text that's ready to dump straight into the final email), the Go code to make this work is pretty simple.  Unfortunately, it wasn't as simple to write as I would have hoped, because the documentation for templates is lacking.

Here's the code:


package main

import ("encoding/csv"; "flag"; "io"; "os"; "text/template")

/// Wrap an array of strings as a struct, so we can pass it to a template
type TWrap struct { Fields *[]string }

/// Parse a CSV so that each line becomes an array of strings, and then use
/// the array of strings with a template to generate one file per csv line
func main() {
 // parse command line options
 csvname := flag.String("c", "a.csv", "The csv file to parse")
 tplname := flag.String("t", "a.tpl", "The template to use")
 fnameidx := flag.Int("i", 0, "Column of csv to use as output file basename")
 fnamesuffix := flag.String("s", "out", "Output file suffix")
 flag.Parse()

 // load the text template
 tpl, err := template.ParseFiles(*tplname)
 if err != nil { panic(err) }

 // load the csv file
 file, err := os.Open(*csvname)
 if err != nil { panic(err) }
 defer file.Close()

 // parse the csv, one record at a time
 reader := csv.NewReader(file)
 reader.Comma = ','
 for {
  // get next row... exit on EOF
  row, err := reader.Read()
  if err == io.EOF { break } else if err != nil { panic(err) }
  // create output file for row
  f, err := os.Create("./" + row[*fnameidx] + "." + *fnamesuffix)
  if err != nil { panic(err) }
  defer f.Close()
  // apply template to row, dump to file
  tpl.Execute(f, TWrap{Fields:&row})
 }
}


This lets me make a "template" file, merge the csv with it, and output one file per csv row.  Furthermore, I can use a specific row of the csv to dictate the filename, and I can provide extensions (which makes the shell script above a tad trickier, but it's worth it).

The code pulls in the csv row as an array of strings.  That being the case, I can wrap the array in a struct, and then access any array entry via {{index .Fields X}}, where x is the array index.

To make it a tad more concrete, here's a sample template:


Programming Assignment #1 Grade Report

Student Name:  {{index .Fields 2}} {{index .Fields 1}}
User ID:       {{index .Fields 0}}
Overall Score: {{index .Fields 3}}/100

The script uses command line arguments, so it's 100% reusable.  Just provide the template, the csv, the column to use as the output, and the output file extension.

The code isn't really all that impressive, except that (a) it's short, and (b) it is almost as flexible as code in a scripting language, yet it runs natively.  The hardest part was finding good examples online for how to get a template to write to a file.  It's possible I'm doing it entirely wrong, but it seems to work.  If any Go expert wants to chime in and advise on how to use text templates or the csv reader in a more idiomatic way, please leave a comment.

Wednesday, April 29, 2015

Saving time with VBA and Outlook

Over the years, I've used Visual Basic for Applications in a lot of ways.  I've never really thought of myself as an expert, but I have written a fair bit of VB scripts, even though I'm mostly a Unix/C++/Java programmer.

One thing I've always appreciated about the VB community is that there is a lot of code sharing.  One script I stumbled on a while back is for downloading all attachments, from all selected files, in Outlook.

Our department scanner will send me a separate email for each file that I scan, which means that I can scan all of my students' assignments, one at a time, and have a digital copy of each.  But forwarding those on to the students is usually a pain.

Enter VBA... I used this script to download all the attachments at once.  Then I used the preview pane in Windows to quickly check that the file names were time-ordered in the same sequence as the students user IDs.  A few lines of bash later, and all 89 pdfs were mailed.  Hooray!

Tuesday, March 17, 2015

Getting Started with JUnit

I had some fun learning about JUnit recently.  I've always believed that it's important to develop incrementally.  The neat thing (to me) about unit testing is that it encourages incremental development -- if you have lots of tests that don't pass, then the natural thing to do is to pick them off, one at a time, and fix them.  In grad school, and now as a professor, I've had a fair number of occasions where someone said "I'm almost done writing it up, I should be ready to compile in a day or two".  Perhaps encouraging students to develop their tests first will discourage them from falling into that pattern of behavior.

Anyhow, I built a tutorial about JUnit, for use in my CSE398 class.  Feel free to share your thoughts on the tutorial, JUnit, and test-driven development in the comments!

Tuesday, March 3, 2015

Callbacks and Scribble Mode

Last week, we had a mobiLEHIGH tutorial session, and a student asked about how to make Fruit Ninja with LibLOL.  It turns out that getting the right behavior isn't all that hard... you can use the "scribble" feature to detect a "slice" movement on the screen, and configure the obstacles that are scribbled to have the power to defeat enemies.

There was just one problem... configuring the obstacles requires changing the LibLOL code.  I don't discourage people from changing LibLOL, but it's better to have an orthogonal way of getting the same behavior.  In this case, it's easy: let the scribble mode code take a callback, and use that callback to modify an obstacle immediately after it is created.

This is one of those changes that I can't help but love... there's less code in LibLOL, and more power is exposed to the programmer.  But it's not really any harder, and there's less "magic" going on behind the scenes now.

Here's an example of how to provide a callback to scribble mode:


    // turn on 'scribble mode'... this says "draw a purple ball that is 1.5x1.5 at the
    // location where the scribble happened, but only do it if we haven't drawn anything in
    // 10 milliseconds."  It also says "when an obstacle is drawn, do some stuff to the
    // obstacle".  If you don't want any of this functionality, you can replace the whole
    // "new LolCallback..." region of code with "null".
    Level.setScribbleMode("purpleball.png", 1.5f, 1.5f, 10, new LolCallback(){
        @Override
        public void onEvent() {
            // each time we draw an obstacle, it will be visible to this code as the
            // callback's "attached Actor".  We'll change its elasticity, make it disappear
            // after 10 seconds, and make it so that the obstacles aren't stationary
            mAttachedActor.setPhysics(0, 2, 0);
            mAttachedActor.setDisappearDelay(10, true);
            mAttachedActor.setCanFall();
        }
    });

I'm starting to think that I should redesign more of the LibLOL interfaces to use callbacks... what do you think?

Saturday, February 21, 2015

Getting Started with OpenCV

OpenCV is a great library for doing all sorts of computer vision.  It's also easy enough that you can use it for all sorts of menial tasks, like resizing images, cropping, adjusting colors, etc.  And best of all, it's FAST.  I have used ImageMagick in the past, and OpenCV feels a ton faster.  If you want some data to support that claim, see this link.

Given that OpenCV is fast, general-purpose, and not too hard to use, I thought it would be a good topic for CSE398.  Here's the tutorial I wrote.

I opted to do everything in Java, because that seemed easier than worrying about memory management.  Of course, that also means it's harder to find good documentation.  I ended up transliterating a lot of C++ code to show how various features work.

Since I'm not expert in Computer Vision, I wouldn't be surprised if I got some things wrong in the tutorial.  Please don't hesitate to send a note if you find any errors!

Monday, February 16, 2015

An Introduction to Extending Code

Here's yet another CSE398 tutorial.  This time it's about how to dynamically load code, or to otherwise create extensions that expand the behavior of a program.  I realized that while students have heard of "DLL Hell", they don't know how to make DLLs (or their Unix equivalent, "shared objects").

DLLs are like lambdas (did you like yesterday's post?): if you don't know how to use them, you end up doing an outrageous amount of work to get an effect that would otherwise be simple.  The tutorial starts by showing how to load and use a shared object in C++, which lets me introduce my basic Makefile template, function pointers, and C++ name mangling.  Then it shows how to do dynamic class loading in Java.  We move from there to using exec or spawn to do inter-process communication (IPC) between Node.js and Java or C++ programs.

I tried to make the tutorial a little bit more fun, by hiding the code for a Java Pig Latin converter.  This was also an attempt to get people to look at the HTML code for my tutorials.  I don't think students realize how easy it is to do clean web design by hand, once you know a little CSS and jQuery.

As with all of my CSE398 tutorials, I wrap up with next steps, this time involving the use of existing Node.js packages to load C++ and Java code directly into a running node server.

Sunday, February 15, 2015

A Few Great C++11 Features

A few years back, I heard a talk by John Spicer of Edison Design Group on new features in C++11. After hearing John's talk, I realized that my students and I all fell into his category of programmers who knew the "FORTRAN subset of C++".  Sure, I've written lots of code over the years, and a C++ compiler will understand that code.  But was it really C++?  Was it idiomatic?  And even if it was, would it still be considered idiomatic in the face of C++11?

C++11 adds tons of cool features.  The concurrency support is great.  The STL is even better than before.  But the best part, in my opinion, is lambdas.  With lambdas, data structure design gets a lot easier.  One "map" function can replace all of those one-off functions that otherwise go into a data structure (min, max, average, selectIf, countIf, etc.).

Here's a program I wrote to demonstrate some of the features of C++11.


/// This is a demonstration of a few nice C++11 features: auto, the ':'
/// iterator, initializer lists, std::function, and lambda expressions.  In
/// many cases, it's possible to achieve the same effect as I present using
/// even less code, but by being explicit I hope I have made the code and
/// comments easy to follow

#include <functional>
#include <iostream>
#include <map>
#include <string>
#include <vector>

using namespace std; // I'm being lazy here... should explicitly use cout,
                     // endl, function, map, pair, string, and vector


/// wrapped_map_t extends map<string, string>.  We start with a map of
/// key/value pairs, where both the key and value are strings, and we add a
/// new method to it.  The new method, apply_to_all, lets us apply a lambda
/// to (a copy of) every key/value pair that is in the map.
///
/// my claim is that lambdas fundamentally change the art of data structure
/// design.  To support my claim, I will show how this one simple function
/// obviates many public functions that one might want int a data structure
/// (count, print, extract_keys, find_matching_keys, etc).
struct wrapped_map_t : public map<string, string>
{
    /// the apply_to_all function simply iterates through the key/value pairs
    /// of the map, calling lambda(key, value) for each pair.  Strictly
    /// speaking, std::map is a red/black tree, and this will do a pre-order
    /// traversal
    void apply_to_all(function<void(const string, const string)>& lambda)
    {
        // note the use of C++11 'auto' keyword to avoid having to specify
        // the type of the iterator
        for (auto i = begin(), e = end(); i != e; ++i)
            lambda(i->first, i->second);
    }
};

int main()
{
    // declare an instance of the extended map
    wrapped_map_t kvpairs;

    // populate the map with some keys and values.  We're going to use some
    // great C++ magic here: initializer lists.  We don't even have to know
    // the type of the list, but the compiler will deduce that it's something
    // like pair<string,string>[]
    kvpairs.insert({{"donald", "duck"}, {"mickey", "mouse"},
                    {"minnie", "mouse"}, {"bat", "man"},
                    {"super", "man"}, {"milo", "otis"},
                    {"mighty", "mouse"}, {"rocky", "squirrel"},
                    {"bullwinkle", "moose"}});

    // 'func' is a reference to a function that takes two strings as its
    // parameters, and returns nothing.  This is a lot nicer than the old C
    // syntax in use before C++11 (i.e., void (*func)(string, string)).
    function<void(string, string)> func;

    // let's assign a new lambda to func.  the lambda will simply print its
    // parameters
    func = [](string k, string v) { cout << "{" << k << ", " << v << "} "; };
    // now let's apply func to every element in the set.  No need for a
    // "print_in_sorted_key_order" function in our class.  It would be
    // trivial to add "print keys" and "print values" features without
    // changing the data structure... we'd just need to pass different
    // lambdas
    cout << "KVPairs = ";
    kvpairs.apply_to_all(func);
    cout << endl;

    // The last example was pretty boring.  A function pointer could have
    // done that easily.  Now let's pass in a function that has a captured
    // reference to a variable that is local to this function.  In that way,
    // each time the lambda is called, it can access the function 'my_count'
    // that we declare *right here*.  The net result is that we can count the
    // elements in the map, without requiring map to provide a "count()"
    // function.  Note that the parameters to the lambda aren't used, and
    // that's OK.
    int my_count = 0;
    func = [&my_count](string k, string v) { my_count++; };
    kvpairs.apply_to_all(func);
    cout << "Elements in map = " << my_count << endl;

    // OK, so we could have achieved that effect with an apply_to_all that
    // took three parameters: string, string, int&.  But would we really want
    // to do that for every possible pass-by-reference type?  For example,
    // here we pass a vector of strings so that we can copy out all keys from
    // the map
    vector<string> keys;
    func = [&keys](string k, string v) {keys.push_back(k);};
    kvpairs.apply_to_all(func);
    // print the keys, to show that it worked
    cout << "Keys in map = {";
    for (auto i : keys)
        cout << i << ",";
    cout << "}" << endl;

    // note, too, that we can use the lambda to capture multiple local
    // variables, and that some can be pass by value while others are pass by
    // reference.  Here 'pre' is pass by value, 'keys' is pass by reference,
    // and our function copies into 'keys' all keys in the map whose values
    // begin with 'mo'
    string pre = "mo";
    keys.clear();
    func = [&keys, pre](string k, string v) { if (v.find(pre) == 0) keys.push_back(k);};
    kvpairs.apply_to_all(func);
    cout << "Keys whose values start with 'mo' = {";
    for (auto i : keys)
        cout << i << ",";
    cout << "}" << endl;

    // this example is much like the prior one.  Here we extract all
    // key/value pairs where the key begins with 'mi'
    pre = "mi";
    vector<pair<string, string>> pairs;
    func = [&pairs, pre] (string k, string v)
        { if (k.find(pre) == 0) pairs.push_back(make_pair(k, v)); };
    kvpairs.apply_to_all(func);
    cout << "Elements whose key begins with 'mi' = {";
    for (auto i : pairs)
        cout << "{"<<i.first<<", "<<i.second<<"} ";
    cout << "}" << endl;

    // the point of this example is to illustrate that when the lambda is
    // called with the key and value, the function we are executing *cannot*
    // modify the internals of the map.  Put another way, the lambda does not
    // become a member function of the class.  So, for example, if we wanted
    // to add a suffix to every key, then the only way we could do it would
    // be by explicitly updating the k/v pair in the map.
    string suf = " <3";
    // note: we need to capture *kvpairs itself* by reference
    func = [&kvpairs, suf] (string k, string v) { kvpairs[k] = v+suf; };
    kvpairs.apply_to_all(func);
    // use a lambda to print it out
    func = [](string k, string v) { cout << "{" << k << ", " << v << "} "; };
    cout << "Modified kvpairs = ";
    kvpairs.apply_to_all(func);
    cout << endl;
}

Don't forget that you need to use the -std=c++11 flag when you compile this with g++.

Saturday, February 14, 2015

Fun with Google Forms

Here's a link to another of my tutorials for CSE398.  I figured this out in the course of making a registration page for an elementary school's after-school enrichment program.  We wanted the convenience of a Google Form, with all results going to a shared spreadsheet, but we also wanted to be able to keep people from registering for activities that were either (a) not available based on their child's grade level, or (b) already at capacity.

The trick is to make a separate worksheet in the Google Spreadsheet that is attached to the form, set it up to summarize the data in the main sheet of the spreadsheet, publish the second worksheet, and only the second worksheet, and then consume it as JSON.  Then it's just a matter of using JavaScript on the client side to fetch the JSON, parse it, and use the resulting data to drive the UI.

Somewhere along the way, I realized that the Google Form is really two components with a straightforward API connecting them.  We can't change the API, but we can have a different front-end that interacts with the same back-end, as long as we respect the API.  Once I realized that, it seemed worthwhile to make a tutorial about it.

The link to the tutorial is here.  Hopefully it is easy to follow.  As with my other CSE398 tutorials, there are "next steps" that I leave up to the student.

Disclaimer: there are ways to hack the technique I present, so don't use it for anything mission-critical.  You'll still get the safety that Google Forms provides, but people can get around the JavaScript-based validation.

Friday, February 13, 2015

My Favorite Graphics Tutorials

This isn't a particularly long post, but if anyone is looking for tutorials to help them make graphics for their mobiLEHIGH games, I think Chris Hildenbrand's tutorials on making vector art with Inkscape are great.  Here are some links:

You can also check out Chris's blog.

Remember: when making art for games, png is the preferred format.  It has transparency support, and it uses lossless compression, so your nice crisp lines won't get blurred like in jpegs.

Thursday, February 12, 2015

Getting started with Node.js

This semester I'm teaching a new class, CSE398: Large Scale Software Development.  The goal of the class is to provide students with a hands-on experience designing and implementing bigger programs than they see in a typical class.  My informal informal motto is "If you need to have a database and a web site, that's not two projects... it's half a project, because you don't have a desktop or mobile component."

That may seem trite, but my feeling is that it's important to use other people's APIs, to connect software components that are implemented in different languages, and to understand that real-world software must be thought of as a large set of loosely connected components.

I'm also hopeful that this will be a great laboratory for learning about technical debt.  In particular, I'm hoping that students will cut corners early in the semester, and then have nobody but themselves to blame when they return to that code later in the semester.  We shall see how it goes.

Anyway, with all of that exposition out of the way, I'll note that a few weeks back, I put together a tutorial on how to do all the basic web things (forms, REST, connect to MongoDB, push notifications) that people do with Node.js.  The tutorial is publicly available through this link.

There are a few bugs in the tutorial, so if you notice anything incorrect, please let me know in the comments, so I can make corrections.

You'll also note that each tutorial has some "next steps", which I expect the students to do without my close guidance.  This is meant to encourage learning about how to teach oneself from on-line tutorials, and also how to evaluate on-line resources.  For what it's worth, I think the scotch.io tutorial series on passport.js is pretty good.

Wednesday, February 11, 2015

Particle Systems

LibGDX has some amazing support for particle systems.  Particle systems provide a way to produce some great effects, like snow or flames.

I just added some basic support for particle systems to LibLOL.  These particles are not Actors.  They don't have meaning in the Physics world.  But they do provide some nice visual effects.

Using particle effects is pretty easy.  There's a new facility, Effect, which provides a factory method for making particle effects.  (Hopefully I'll add other effects some day, so I made the code a little bit generic.)  All you need to do is provide the name of a particle effect file, give it x and y coordinates, and then indicate a few other parameters (Z index, whether it should repeat).

The hard part is making the particle effect file.  There's a tutorial here.  In effect, there are three parts:

First, you need to set up Android Studio to run the particle effect editor.  This is a lot like the step you took to make a "Desktop" target for your game.  You'll use the "Run/Edit Configurations" menu option, and set the path to "com.badlogic.gdx.tools.particleeditor.ParticleEditor".  If you've done it correctly, you'll be able to choose ParticleEditor from the run options.  Running it should start a program that looks like this:


Second, you can play with all of the parameters in the program until you get the effect you want.  To do this correctly, your best bet is to set Pixels per meter to 20 (because LibLOL has a pixel-to-meter ratio of 20).  Once you've done that, you'll need to divide a lot of the values in the editor by 20 to get things back to a reasonable state.  Once you've got everything looking good with 20 pixels per meter, save the effect as a text file in your android/assets folder.

The third step is to load your effect, see what doesn't work nicely, and adjust accordingly.  I know it's unsatisfying to say "trial and error", but sometimes that's what it takes.

Tuesday, February 3, 2015

Making Games in Liblol: Part 6: The Store

While this post title is "The Store", this is really about another component of LibLOL: the "Facts" interface.

In most games, there are things (typically numbers) that you might want to save.  During the play of a single level, you might want to count how many power-ups the player used.  During one interaction with the game (such as playing 18 holes of golf), you might want to keep track of the score on each hole.  You might also want to track some statistics relating to the history of every time the game has been played.

While you can manage most of this using fields in the objects of your game, it's often easier to have a unified interface.  That's where Facts comes in.

Facts come in a few flavors: first of all, we can store numbers related to the current level being played (LevelFacts), to the current interaction with the game (SessionFacts), or with the whole game (GameFacts).  For each of these, we can either put a fact as a string and an integer value, or we can get a fact, again as an integer value.

For the sake of completeness, I'll note that there is one special case for Facts: we can also save and retrieve actors (Goodies, Obstacles, Heroes, Enemies, Projectiles) for the current level, also as LevelFacts.

Getting back to our store example, the main idea is that we can use Actors in the store to represent buttons for things to purchase.  In a level, as we collect coins, the level's internal score increases.  To turn the coins of the level into a Fact, we can do something like this:


            LolCallback sc = new LolCallback() {
                public void onEvent() {
                    int oldCoins = Facts.getGameFact("Coins", 0);
                    int addedCoins = Score.getGoodiesCollected1();
                    Facts.putGameFact("Coins", oldCoins + addedCoins);
                }
            };
            Level.setWinCallback(sc);

Putting that code in our level will say that when the level is won, we'll add the score (score 1, to be precise... remember that we have counters for four different kinds of scores) to the old coin count.

We could get more fancy, for example by having callbacks on our coins so that we could directly add to a specific LevelFact.  But for our example, this is good enough.

What about the store, then?  Well, it's pretty simple: we can have obstacles on a store screen to represent buttons for purchasing power-ups, and then we can have TouchCallbacks on the buttons that subtract from the Facts to make a purchase happen.  Those callbacks should also update other GameFacts to indicate the numbers of power-ups remaining.

Hopefully that's enough information to get you started building a store for your app.  But I do have one question: are integer and Actor Facts enough?  Would String facts be useful?  Let me know in the comments.

Thursday, January 15, 2015

All About Actors

Within a level of your game, just about everything of interest involves an actor.  The idea behind an actor is that it encapsulates a visible thing in the game world, and that it can be involved in collisions.

There are different types of actors in a game.  In LibLOL, there are some pre-defined kinds of actors, and they have certain behaviors and properties attached to them, as described below:

Heroes


The hero is usually, but not always, the focal point of the game.  Whenever a hero collides with something, it's probably important: it could be an enemy that causes harm to the hero, an obstacle that re-enables the hero's ability to jump, a goodie to collect, etc.

Every hero in the game has a certain amount of strength (initially set to 1), and when a hero's strength drops to 0, that hero is removed from the game.  If all the heroes are gone, then the level ends in defeat.  You can also specify that once a certain number of heroes are gone, the level ends in defeat, to capture the idea that you need to keep 3 of 5 heroes from being defeated.

Heroes are usually the focal point for controlling the movement of the game.  In tilt games, the hero usually moves with the tilt of the phone, and otherwise there are usually buttons for making the hero move, jump, and duck.  But that's not always the case.  For example, sometimes it's useful to have an invisible enemy at the bottom of the screen, with enemies falling from the sky.

Enemies


These are the "bad guys" in a game.  They have an amount of damage assigned to them, so that whenever the hero collides with the enemy, it loses strength.  Strictly speaking, when a hero collides with an enemy, we check if the hero strength is greater than the enemy's damage value.  If it is, the hero's strength decreases and the enemy disappears.  Otherwise, the enemy's damage decreases and the hero disappears.

Enemies can take all sorts of forms and shapes.  An invisible enemy at the bottom of a pit is a good way to detect when the hero fails to make a tricky jump.  Every fireball shooting from the dragon's mouth is probably an enemy.  Spikes and fires are probably enemies.  And actors who move around and get in the way of the hero are often enemies.

There are a few ways to defeat an enemy.  As described above, you can defeat an enemy by colliding it with a hero, as long as the hero has more strength than the enemy has damage.  Enemies can also be marked so that they are defeated by colliding with a hero who is crawling or jumping (in which case the hero strength does not change).  By default, an invincible hero will defeat any enemy it touches (but you can disable this for certain enemies).  It's also possible to defeat an enemy by throwing projectiles at it, or by colliding it with an obstacle that has a collide callback.  Naturally, you can find examples of all these behaviors in the levels of the sample game.


Obstacles


This might sound trite, but when in doubt, consider using an obstacle.  Obstacles in LibLOL have grown from being static objects like walls and floors into being the primary mechanism for handling callbacks.  By using the "toggleCollisionEffect", you can make it so that your obstacle doesn't impede the movement of other actors, while still causing a callback to run.  There are many pre-defined callbacks (such as for boosting a hero's velocity when it collides with the obstacle).  When you can't find the behavior you need, your next best bet is to use a collision callback.  You can use these to defeat enemies (by calling remove() on the enemy), to win or lose the game, to change the score, etc.

In another post, I'll talk about how to make "infinite" games by using collisions with obstacles as a way to know when to draw the next part of the level.


Goodies


Goodies are things that the hero collects.  As a hero collects goodies, they disappear, and they get added to one of four score counters.  It's possible to use these score counters as a way to activate destinations, or even to win the game ("win by collecting two apples, a banana, and six celery"). Goodies can be configured to increase the hero's strength, or to cause the hero to become invincible.

When the level ends, the goodie counts get reset.  If you need to keep the counts for longer, you'll need to look at using a callback at the end of the level to add the scores to a session Fact or a game Fact.



Projectiles


Projectiles are things the hero throws.  Normally, the idea is that the hero throws projectiles at the enemy, to defeat it.  But don't let that get in the way of being creative... perhaps the projectile is a basketball, and the enemy is an invisible spot in the middle of the basketball hoop, so that each successful basket gets counted via the mechanism for defeating enemies.

If we made a projectile every time a projectile needed to be thrown, we could end up making thousands of projectiles.  That would be inefficient.  Instead, LibLOL has a projectile pool.  Once you've configured the pool, any attempt to throw a projectile begins by choosing one from the pool.  This is more efficient when your game is running, but it saves you code, too, since you can configure a pool once, and then avoid configuring each projectile that is thrown.

Projectiles always are thrown by a hero, and they depart from some point on the hero's body.  The offset parameters to the pool specify where the projectile should start.

When throwing a projectile, there are two techniques: you can either throw at a fixed velocity, or you can throw at an angle.  This latter technique is very nice: when you press the screen, the hero will throw toward the point that you pressed.  By altering the projectile gravity, and by modifying how it behaves upon collision with obstacles, you can achieve projectiles that behave like bullets, grenades, and basketballs, to name a few.

Destinations


Some games, especially mazes, require a hero to reach a destination.  In LibLOL, there is a special actor for this.  Destinations are pretty simple: they can hold as many heroes as you allow them to hold, and they can be configured so that they don't hold any heroes until a certain score is achieved (a certain number of goodies are collected).

SVG Lines


Depending on when you read this document, there might be an actor type for SVG lines.  If so, ignore it.  It's going away soon.


All Actors


There are behaviors and properties that are common to all actors, like animation, route-based movement, and collision callbacks.  Be sure to look at the LibLOL JavaDocs for more information.

Monday, January 12, 2015

Making Games in Liblol: Part 5: The Level Chooser

The level chooser code (Chooser.java) has changed a lot over the years.  Back in the early days, I auto-generated it, and programmers had no control over how it looked.  Obviously that wasn't popular, because it meant that even the tiniest customization required students to jump off a cliff.



The next version of the level chooser code entailed me providing some code to draw the chooser, and the programmer overloading a couple dozen getters that parameterized how the chooser was drawn (things like font size, font face, font color, number of rows of buttons, number of columns of buttons, etc.).  That was better, but the amount of code was way too high for the amount of customization that most people wanted.  And, worse yet, there were still a lot of students who had to jump over the cliff to get the chooser screens they wanted, because I didn't give a getter for everything.

That brings us to the new Chooser.  It serves a few goals:
  • The cliff is gentler... in fact, I draw the chooser slightly differently from one page to the next, to illustrate an increasingly advanced programming style.
  • The total lines of code actually decreased, since the Chooser is yet another ScreenManager.
  • Total customization is now possible, without jumping into my code.
  • There is physics in the Chooser, so animations and other nice visual effects are possible.
There are still a few declarative parameters that are useful.  In MyGame.java, in the configure() function, you'll see these three lines:


        mNumLevels = 92;
        mUnlockAllLevels = true;
        mEnableChooser = true;

The first specifies the number of levels.  This is used at the end of the last level to indicate that the game should go back to the chooser, since there's no level 93.  We'll get to the other two variables later.

Drawing Chooser Screens


The chooser code has a few helper functions in it.  You can always write helper code and then use it in your Chooser (or your Splash, or Level, or Store).  My helper functions let me draw a chooser button (an image with text over it, where pressing the image takes you to a specific level) and draw navigation buttons (for moving to the next or previous chooser screen, and for going back to the splash screen).  These functions aren't very interesting, so I'm not going to bother describing them.

Let's take a look at the code for the first level of the chooser:

        // screen 1: show 1-->15
        //
        // NB: in this screen, we assume you haven't done much programming, so
        // we draw each button with its own line of code, and we don't use any
        // variables.
        if (which == 1) {
            Level.configure(48, 32);
            Physics.configure(0, 0);

            // set up background and music
            Util.drawPicture(0, 0, 48, 32, "chooser.png", 0);
            Level.setMusic("tune.ogg");

            // for each button, draw an obstacle with a touchCallback, and then
            // put text on top of it. Our buttons are 5x5, we have 1.5 meters
            // between buttons, there's an 8.5 meter border on the left and
            // right, and there's an 11 meter border on the top
            drawLevelButton(8.5f, 16, 5, 5, 1);
            drawLevelButton(15f, 16, 5, 5, 2);
            drawLevelButton(21.5f, 16, 5, 5, 3);
            drawLevelButton(28f, 16, 5, 5, 4);
            drawLevelButton(34.5f, 16, 5, 5, 5);

            drawLevelButton(8.5f, 9.5f, 5, 5, 6);
            drawLevelButton(15f, 9.5f, 5, 5, 7);
            drawLevelButton(21.5f, 9.5f, 5, 5, 8);
            drawLevelButton(28f, 9.5f, 5, 5, 9);
            drawLevelButton(34.5f, 9.5f, 5, 5, 10);

            drawLevelButton(8.5f, 3f, 5, 5, 11);
            drawLevelButton(15f, 3f, 5, 5, 12);
            drawLevelButton(21.5f, 3f, 5, 5, 13);
            drawLevelButton(28f, 3f, 5, 5, 14);
            drawLevelButton(34.5f, 3f, 5, 5, 15);

            // draw the navigation buttons
            drawNextButton(43, 9.5f, 5, 5, 2);
            drawSplashButton(0, 0, 5, 5);
        }

This is the kind of code that nobody should ever write.  We're drawing 15 buttons, and their positions are being provided manually in the code.  There are so many other ways of doing this and the other ways have two very important benefits.  First, they take much less code.  Second, when you want to change the behavior, these other techniques let you change one declaration, instead of changing a bunch of function calls.

Let's try to do a little bit better for the second chooser screen.  We'll use a loop to draw the 5 buttons in each row:


        // screen 2: show levels 16-->30
        //
        // NB: this time, we'll use three loops to create the three rows. By
        // using some variables in the loops, we get the same effect as the
        // previous screen. The code isn't simpler yet, but it's still pretty
        // easy to understand.
        else if (which == 2) {
            Level.configure(48, 32);
            Physics.configure(0, 0);

            // set up background and music
            Util.drawPicture(0, 0, 48, 32, "chooser.png", 0);
            Level.setMusic("tune.ogg");

            // let's use a loop to do each row
            float x = 8.5f;
            int level = 16;
            for (int i = 0; i < 5; ++i) {
                drawLevelButton(x, 16, 5, 5, level);
                level++;
                x += 6.5f;
            }

            x = 8.5f;
            for (int i = 0; i < 5; ++i) {
                drawLevelButton(x, 9.5f, 5, 5, level);
                level++;
                x += 6.5f;
            }

            x = 8.5f;
            for (int i = 0; i < 5; ++i) {
                drawLevelButton(x, 3, 5, 5, level);
                level++;
                x += 6.5f;
            }

            // draw the navigation buttons
            drawPrevButton(0, 9.5f, 5, 5, 1);
            drawNextButton(43, 9.5f, 5, 5, 3);
            drawSplashButton(0, 0, 5, 5);
        }

In that code, we use the variable 'x' to store the x coordinate of the next button to draw, and we reset it after each row.  If we wanted to change the spacing between buttons, we could just change 'x += 6.5f' in three places, instead of re-doing the math for 15 buttons.  Naturally, we can also use a loop to do the three rows:


        // screen 3: show levels 31-->45
        //
        // NB: now we use a nested pair of loops, and we can do three rows in
        // just a few more lines than one row.
        else if (which == 3) {
            Level.configure(48, 32);
            Physics.configure(0, 0);

            // set up background and music
            Util.drawPicture(0, 0, 48, 32, "chooser.png", 0);
            Level.setMusic("tune.ogg");

            // let's use a loop to do each row and each column
            float y = 16;
            int level = 31;
            for (int r = 0; r < 3; ++r) {
                float x = 8.5f;
                for (int i = 0; i < 5; ++i) {
                    drawLevelButton(x, y, 5, 5, level);
                    level++;
                    x += 6.5f;
                }
                y -= 6.5f;
            }

            // draw the navigation buttons
            drawPrevButton(0, 9.5f, 5, 5, 2);
            drawNextButton(43, 9.5f, 5, 5, 4);
            drawSplashButton(0, 0, 5, 5);
        }

Now there's one place where we specify the space above the top row (16), one place where we specify the space to the left of the first column (8.5f), and one place for each of the horizontal and vertical spacing of the buttons (6.5f and -6.5f, respectively).  This code is much more maintainable, and it's also much shorter.

You should look at the trick used to draw screens 4-7 in one arm of the if statement.  If all of your chooser screens look the same, you can draw them without adding much code at all.  And if you need to fine-tune specific aspects of the chooser screens, you can do that by using the more verbose code.

Pressing the Back Button


Android devices have a "back" button, and we need to do the right thing when it is pressed.  In LibLOL, pressing back from a level takes you to the appropriate chooser screen, and pressing back from the chooser takes you to the splash screen.  Pressing back from any help or store level takes you to the splash screen.  In games without a chooser, you can set the mEnableChooser field to false (MyGame.java::configure()) to indicate that pressing back from a level should go to the splash screen.

Locking Levels


In LibLOL, a level gets unlocked when you succeed in finishing the previous level.  The other option is to set mUnlockAllLevels, and then everything is unlocked, all the time (this is really helpful when debugging).  The chooser code I provided will look at the lock status and figure out if a button should be active or not.

If you want to require a certain score to unlock the next level, then you'll need to make a few changes.  First, you'll need to set up a Win Callback (see level 32 for an example) so that you can record the fact of the level being unlocked.  The Facts subsystem is used for this.  In Facts, there are "level facts", "session facts", and "game facts", corresponding to information that gets reset when the level ends, when the player quits the game, and never).  You'll need to set up a PostScene that doesn't let you move on to the next level, if that's not appropriate (you can add a callback control that covers the whole screen).  And then you'll need to edit the code for drawing chooser buttons, so that the condition for unlocking a level involves the game fact that you saved.

Sunday, January 11, 2015

Making Games in Liblol: Part 4: The Help System

Back before I switched Splash, Level, Chooser, Help, and Store to the unified "ScreenManager" (a.k.a., physics level) interface, the help scenes of a LibLOL game had to call special functions.  Those days are gone.  A help scene in LibLOL is just a playable level.

So why am I making a blog post about it?  Well, two reasons.  The first is that my Help demos show something interesting: you don't have to use "win" and "lose" to get from one level to the next.  This is pretty nice, because the default behavior is to print a message ("Good Job") when a level is won.  By having a callback control that covers the whole screen, you can go directly from one help scene to the next.  For reference, here's the code:

            // set up a control to go to the next level on screen press
            Control.addCallbackControl(0, 0, 960, 640, "", new LolCallback() {
                public void onEvent() {
                    Lol.doHelp(2);
                }
            });
You can even do this in your levels, just like you can do it in your help scenes.

The other reason I wanted to mention the help scenes is that a lot of games don't have separate help, but the help facility is still useful.  You could stitch your levels and help scenes together, so that winning a level took you to a help scene for the next set of levels, and after the help scene you would go to the next level.  You could also use help scenes as a way of presenting credits, to show who designed your game.  Another use is hiding secret features in the help scenes.  For example, you could have an invisible button on the help screen, and if the player touches it, 50 coins get added to the wallet, for use in the store.

Oh, and don't forget that you are not required to chain all of your help scenes together with "next" buttons.  You could use scenes 1-10 to provide standalone help, scene 11 to list best scores, and then make help scene 12 be a secret level that gets unlocked through some in-game accomplishment.

If you have any creative uses of the help scenes, be sure to leave a comment!

Saturday, January 10, 2015

Making Games in Liblol: Part 3: Configuring the Splash Screen

The folks at Studyhall Entertainment put out a new game using LibLOL, and on the splash screen, they had animations.  My first thought was that it was a really clever effect (and they even took control of the "back" button as a way of re-generating the animation... sweet!).  But then I started to wonder how they even did it, since the LibLOL splash screen was didn't have physics support.

Long story short, I decided to make the splash screen (and the chooser, and the help screens) into a physics world.  This meant throwing out a lot of code, and then making the splash screen adopt the same interface as playable levels.  Now there's less code for me to maintain, and fewer interfaces for programmers to learn.  Win-win.

To explain the splash screen, it's going to be useful to discuss a few other concepts first:

The Heads-Up Display

There are times when we want to draw things on the camera, instead of in the world.  A great example of this is in Mario-style games.  No matter where the hero is, we want the time, number of lives, and coin count in the top-left corner.  Putting text in the world wouldn't work: as Mario moves, the text would scroll off the screen.  In a phone game, where touching the screen is a way of controlling the action, we might also want to draw buttons on the camera instead of the world.  

It is confusing to think of "drawing on the camera", so games use the term "heads-up display", or HUD, to refer to anything drawn on the camera.  In LibLOL, we can put information (images and text) onto the HUD through the "Display" feature, and we can put buttons onto the HUD through the "Control" feature.

Callbacks

Recall that a game is a simulation.  Part of what that means is that we can change the state of the simulation in response to special events, like screen touches.  But that also means we need to be able to provide code that doesn't run until the event happens.  Callbacks are a way of providing this functionality.  Consider the following code:


        Control.addCallbackControl(96, 186, 160, 80, "", new LolCallback() {
            public void onEvent() {
                Lol.doHelp(1);
            }
        });

This code says "draw a button on the screen, and when the player presses it, run the code I'm providing".

In truth, most of the code for making controls in LibLOL is much simpler than this, because I provide the code to run when the button is pressed.  You don't need to write your own callbacks for jumping, running, ducking, throwing projectiles, and so on.  Callback controls are really only for custom behaviors.  But since they're there, I wanted to demo them, and what better place than the splash screen?

Let's look at this code in more detail.  We are drawing a control with a bottom left coordinate of (96, 186), a width of 160, and a height of 80.  We are not providing an image for the control (""), and hence it is invisible.  We could give an image, which would be drawn on top of the world.  We could give a partially-transparent image, too, so that the world would be visible through the image of the control.  But that's not important right now.

What is important is the last part of the code: "new LolCallback() { ... });"  This is a lot of text, and in the end, it's just to say "run Lol.doHelp(1) when the control is pressed".  Java 1.8 provides a cleaner way of writing this code, but Android Studio doesn't support Java 1.8 yet.  When it does, this code will get a lot cleaner.

If callbacks don't make complete sense right now, it's OK.  Most Computer Science programs don't teach callbacks (technically "anonymous classes") until students have a few semesters of experience.

Drawing the Splash Screen

Now that we've covered those details, let's look at the Splash.java code:


   /**
     * There is usually only one splash screen. However, the ScreenManager
     * interface requires display() to take a parameter.  We ignore it.
     */
    public void display(int which) {
        // set up a simple level. We could make interesting things happen, since
        // we've got a physics world, but we won't.
        Level.configure(48, 32);
        Physics.configure(0, 0);

        // draw the background. Note that "Play", "Help", and "Quit" are part of
        // this background image.
        Util.drawPicture(0, 0, 48, 32, "splash.png", 0);

        // start the music
        Level.setMusic("tune.ogg");

        // This is the Play button... it switches to the first screen of the
        // level chooser. You could jump straight to the first level by using
        // "doLevel(1)", but check the configuration in MyLolGame... there's a
        // field you should change if you don't want the 'back' button to go
        // from that level to the chooser.
        Control.addCallbackControl(384, 182, 186, 104, "", new LolCallback() {
            public void onEvent() {
                Lol.doChooser(1);
            }
        });

        // This is the Help button... it switches to the first screen of the
        // help system
        Control.addCallbackControl(96, 186, 160, 80, "", new LolCallback() {
            public void onEvent() {
                Lol.doHelp(1);
            }
        });

        // This is the Quit button
        Control.addCallbackControl(726, 186, 138, 78, "", new LolCallback() {
            public void onEvent() {
                Lol.doQuit();
            }
        });

        // Mute button is a tad tricky... we'll do it as an obstacle
        Obstacle o = Obstacle.makeAsBox(45, 0, 2.5f, 2.5f, "");
        // figure out which image to use for the obstacle based on the current
        // volume state
        if (Lol.getVolume()) {
            o.setImage("audio_off.png", 0);
        } else {
            o.setImage("audio_on.png", 0);
        }
        // when the obstacle is touched, change the mute and then update the
        // picture for the obstacle
        o.setTouchCallback(0, 0, 0, 0, false, new LolCallback() {
            public void onEvent() {
                Lol.toggleMute();
                if (Lol.getVolume()) {
                    mAttachedActor.setImage("audio_off.png", 0);
                } else {
                    mAttachedActor.setImage("audio_on.png", 0);
                }
            }
        });
    }

That looks pretty complicated, but it's not.  Let's break it down:

  • The splash screen is just a level, so the first two lines set up a simple level with no default forces.
  • We don't actually draw the "Play", "Help", and "Quit" buttons... we just display this picture as the background:

  • We turn on music with one line of code.
  • Then we draw three invisible buttons over the "Help", "Play", and "Quit" text, with callbacks for switching to the help screens, switching to the chooser, or quitting the game.
  • We draw a mute button as an obstacle.  We put a callback on the obstacle to toggle the state of the speakers (muted or unmuted).  The callback also changes the obstacle's image to correspond to the speaker state.
The mute button is definitely the trickiest part.  If it doesn't make sense, don't worry about it.  If you have a mute button, you'll probably only be concerned about where to put it, its size, and what images to use.  You should be able to figure out how to change those aspects of the code pretty easily.

Taking Advantage of Debug Support

One of the most common questions students ask is "How do I know what values to use for the coordinates of my buttons?  There's a nice trick here.  In MyGame.java, the configure() function can set "mShowDebugBoxes" to true or false.  When it's true, and I play the game, every control in the game will be outlined, as will every actor.  In the splash screen, it looks like this:
This means you can see where the buttons are.  But is it necessary to guess about button placement?  Not really.  When the debug boxes are enabled, then LibLOL also prints diagnostic information on every click.  Let's take a look:
In the screenshot above, I enabled the "Run" view in the bottom left corner.  Then I started the desktop version of the game, and I clicked once on an area of the game window.  As you can see, the log shows the screen coordinates (in pixels), corresponding to where on the "camera" I touched, and it also projects these to the world coordinates (in meters) where my touch would have happened in the physics world.

Note, too, that there are a few error messages about LibLOL not finding image files.  These messages can be really helpful if you mistype a file name.  So for as annoying as it can be to have those boxes showing when you are developing your game, it's a good idea to keep them enabled until you're ready to put your game on the market.  Once you get used to them, they can save you a ton of time!

Friday, January 9, 2015

Making Games in Liblol: Part 2: Creating Levels

In LibLOL, we put the code for all of the levels into a single file called "Levels.java".  If you open that file, you'll see that there's one method, called "display()":


    /**
     * Display one of the screens
     *
     * @param which The screen to display. Your code should use an /if/ statement
     *              to decide what screen to display based on the value of /which/
     */
    void display(int which) {
        ...
    }

Inside of this method, you'll see that there's a lengthy "if" statement:


    if (whichLevel == 1) {
        ...
    }

    else if (whichLevel == 2) {
        ...
    }
    ...

The code for each level is self-contained in one of these "if" blocks.  Technically, you don't have to do things this way, and when your game gets sufficiently complex, you'll want to change things.  But for now, it's easier to just put all of your code in one place.

Everything is an Event

Writing games is different than writing the kind of code that most people learn in their introductory computer science classes.  Fundamentally, a game is a simulation.  At all times, the game has some sort of state, and some rules that apply to that state.  At fixed intervals (every 1/60th of a second), the rules are applied to the state of the game to produce a new state.  So, for example, if the state consists of a single actor at position (0, 0) with a velocity of (6, 6), then after one interval passes, the rules will be applied, the actor will be moved to (.1, .1), and the game will be re-drawn.

When the player interacts with the game, either by tilting the phone or touching the screen, it creates an event.  Similarly, when certain special collisions happen between the actors in the game, or when timers expire, we have events.  The way to change the state of the game is in response to events.

The first event that matters is the event for starting a level.  Our "display" function is precisely for this purpose.  When the player touches a button on the chooser, then display() will be called, with the selected level passed in as whichLevel.  Our code runs in response to that event, to configure the initial state of the game.  It's important to remember that your game won't start playing until you finish drawing the initial state.  So, for example, you can't draw an infinitely long level in the display() code, or you'll never get to the point where you can start playing the game.

With that said, let's look at how to draw a level.

A World, and a Camera

LibLOL only supports 2D games (LibGDX, on which LibLOL is built, allows 3D games).  It also is heavily attached to the Box2D physics simulator.  What this means is that by default, every actor in the game is going to be a physical body.  Every actor has density, friction, and elasticity.  Every actor can be involved in collisions with other actors.  Every actor is able to move, and that movement is governed by the laws of physics.  If we don't want these sorts of behaviors, we have to turn them off.

The simulation I mentioned above, then, is simulating a physics world.  But how big is that world?  How much of it can we see at any time?  The easiest way to think about this is to imagine that you have a huge sheet of paper on your desk, on which you've drawn a picture.  Then hold your phone exactly one foot above the picture, and switch to your camera app.  The camera can only see part of the picture, and as we move the camera, different parts of the picture become visible.  The piece of paper on your desk is the physics world.  The phone corresponds to what we'll think of as the "viewport", or "camera".  And the fact that we're holding the phone exactly one foot above the paper is important.  Here's a picture that might help:


In the picture, the shape with the red outline is the world.  The shape with the purple outline is the camera.  The blue dotted lines show a projection from the world onto the camera, so that we can see just a portion of the world at any time.

In LibLOL, the coordinate system starts in the bottom left corner.  So (0, 0) is bottom left, and as we move up and to the right, the y and x values get larger, respectively.

The last important aspect here is the relationship between the units of the world and the units of the camera.  We're going to measure our world in meters, and our camera in pixels.  In LibLOL, there are 20 pixels per meter.  We're also going to assume that the camera is 960 pixels wide by 640 pixels high.  LibGDX will stretch our game to look nice on any phone, but starting with a 960x640 camera (which shows 48x32 meters) gives good resolution and a good width-to-height ratio for most phones.

A Very Simple Level

Now that we've gone over those details, we can start writing the levels of a game.  Remember that the game levels that you get when you check out the LibLOL code are meant to demonstrate how to use the code, and that you're encouraged to change them as you learn, and then replace them as you create your own game.  Let's take a look at level 1 of the demos:


        /*
         * In this level, all we have is a hero (the green ball) who needs to
         * make it to the destination (a mustard colored ball). The game is
         * configured to use tilt to control the hero.
         */
        if (whichLevel == 1) {
            // set the screen to 48 meters wide by 32 meters high... this is
            // important, because Config.java says the screen is 480x320, and
            // LOL likes a 20:1 pixel to meter ratio. If we went smaller than
            // 48x32, things would get really weird. And, of course, if you make
            // your screen resolution higher in Config.java, these numbers would
            // need to get bigger.
            //
            // Level.configure MUST BE THE FIRST LINE WHEN DRAWING A LEVEL!!!
            Level.configure(48, 32);
            // there is no default gravitational force
            Physics.configure(0, 0);

            // in this level, we'll use tilt to move some things around. The
            // maximum force that tilt can exert on anything is +/- 10 in the X
            // dimension, and +/- 10 in the Y dimension
            Tilt.enable(10, 10);

            // now let's create a hero, and indicate that the hero can move by
            // tilting the phone. "greenball.png" must be registered in
            // the registerMedia() method, which is also in this file. It must
            // also be in your android game's assets folder.
            Hero h = Hero.makeAsCircle(4, 17, 3, 3, "greenball.png");
            h.setMoveByTilting();

            // draw a circular destination, and indicate that the level is won
            // when the hero reaches the destination. "mustardball.png" must be
            // registered in registerMedia()
            Destination.makeAsCircle(29, 26, 2, 2, "mustardball.png");
            Score.setVictoryDestination(1);
        }

There are only seven lines of code.  Let's work through them, one at a time.

  • Level.configure() -- This line should always be the first line of code when drawing a level.  It is responsible for saying how big the physical world is for this game.  We've made it 48 meters x 32 meters, which is as small as a level can be, given the size of our camera and our pixel-to-meter ratio.  In general, if you're making a non-scrolling game, these dimensions are good.  When this line of code finishes, there is a physical world into which we can place actors.
  • Physics.configure(0, 0) -- This line indicates that there are no default forces acting on actors in the level.  This makes sense for a game where the player is supposed to be looking down at the action.  For a Mario-style game, where the view is from the side, (0, -10) is a common setting.
  • Tilt.enable(10, 10) -- This level is going to use the tilt of the phone (note: when running on the desktop, use the arrows to simulate tilt).  The numbers passed to this function set thresholds for how much force you can produce via tilting.  In this case, no matter how steep the angle, we'll say that the phone produces no more than 10 units of force.
  • Hero.makeAsCircle(4, 17, 3, 3, "greenball.png") -- This line creates an actor who is a "hero".  The hero will be drawn such that it is 3 meters wide by 3 meters high, and its bottom left corner will be at the coordinate (4, 17).  If that didn't make sense, take a look at the following image, which would correspond to Hero.makeAsCircle(7, 10, 3, 3, "greenball.png")
  • h.setMoveByTilting() -- This indicates that the hero we just made is going to be controlled by the tilt of the phone.
  • Destination.makeAsCircle(29, 26, 2, 2, "mustardball.png") -- This draws the destination (the place the hero must reach).
  • Score.setVictoryDestination(1) -- There are many ways to win a level... surviving for long enough, defeating enough enemies, collecting enough goodies, etc.  In this case, we are saying that once one hero reaches the destination, the level should end.
You should feel free to modify these lines of code and see what happens.  Change numbers.  Delete lines.  In some cases, your game will still work.  In others, Android Studio will inform you that your code is no longer valid.  Once you get comfortable with level 1, move on to subsequent levels and start exploring.  Hopefully you'll find that LibLOL makes it easy to get very advanced effects using only a small number of lines of code.