Frogatto & Friends

Frogatto sprite

Frogatto & Friends is an action-adventure platformer game, starring a certain quixotic frog.
We're an open-source community project, and welcome contributions!
We also have a very flexible editor and engine you can use to make your own creations.

Update Regarding 1.3 Release Candidates

November 15th, 2012 by Jetrel

We’ve updated our most recent post with new mac and windows builds that fix a major bug that cropped up. If you started playing on challenging, the bug would end up changing the difficulty back down to casual, when you died and respawned. Since having another difficulty level is a cornerstone of this release, if you’d already downloaded the previous one and feel like challenging doesn’t change anything, you probably want to download again.

This is especially embarrassing to us since we’ve put so much time and effort into having another difficulty level. It seems that the reason we never found it is that almost every time we tested the higher difficulty, we used a special commandline option to jump-start the game on a level later into the game, with higher difficulty (allowing us to test the game in segments). Because this option internally works in slightly different way than our difficulty-selector screen, it prevented the “revert to casual” bug from happening to us. There are several lessons to be learned about software QA here. 😐

Thanks for sticking with us, sorry if that bug means you needed to download again.

FacebooktwitterredditmailFacebooktwitterredditmail

Frogatto 1.3 Release Candidates

November 10th, 2012 by Jetrel

We’re almost done with 1.3 at this point, and we’ve got a mac build and a windows build ready for final testing (linux users will need to compile from source). If you’re interested in testing, please download these and post about any bugs on our forum! We don’t have the mobile versions of 1.3 done yet (we’re fixing some last few bugs that are mobile-only).

We have screenshots up for 1.3 if you’d like a peek at what’s to come. There are also several great new songs in 1.3; this is the new centerpiece for seaside (seriously, I ****ing love this song), this one kicks off the forest area, and this is the new theme for frogatto himself.

In this release candidate, we’ve included all translations, even those which are currently mostly-unfinished; we’re going to ship the final version of 1.3 without the unfinished ones. If you’d like to help out with translations, you can read a guide on helping out, and can chip in on our transifex page, which lets you look at a side-by-side listing of the original english lines, and blanks you can fill in with a translation to your language.

Thanks in advance for all your support, guys!

FacebooktwitterredditmailFacebooktwitterredditmail

Shaders in Frogatto

October 28th, 2012 by Sirp

I’ve been playing around with some OpenGL shader features in Frogatto. Here are some videos showing what I’ve come up with:

FacebooktwitterredditmailFacebooktwitterredditmail

Translator Quest

September 30th, 2012 by marcavis

So, over the past few weeks, we’ve been edging closer and closer to releasing a new Frogatto version.

There have been plenty of changes since the latest version – some under the hood, but also we’ve been improving the content on several fronts – better balancing, new enemies, new songs, and much more.

So, as Frogatto 1.3 is better than ever (but not as good as 1.4 will be, later on), we’d love to make the game accessible to as many people as possible. There’s only so far we can do that by ourselves, though – translations are key to let us reach a wider audience. Can you help us with that?

If you have a solid grasp of a language to which you’d like to translate Frogatto, check out our page at Transifex, which is where our translations are managed: https://www.transifex.net/projects/p/Frogatto/

There are also some guidelines to the translation process in this forum post, so check it out, too.

FacebooktwitterredditmailFacebooktwitterredditmail

Realtime Images

September 3rd, 2012 by DDR

Recently, we’ve added a brand-new feature to our editor. Images now get reloaded in real-time, while you’re playing the game in the editor.

If you’re an artist and you’ve spotted a tiling bug with some part of the ground, you don’t have to stop playing (and loose your position) to fix up the error. You just edit the source image, save it, and there it is in-game. This is especially useful when creating animations, since you can see the animation as it is played in its natural environment. It’s also quicker – animating with a live preview is much better than animating in a situation where you have to wait for everything to load before you can see the results of your efforts.

This also has implications if you’re prerendering your art. I’ve been working on a little project for the past few months which uses Blender 3D to render the graphics. In the following video, I demonstrate the results of telling Blender to output its rendered images to the game’s graphics folder. (The change is a bit exaggerated, but it’s to make a point.)

Although there is a bit of a delay in rendering, the time cut off having to start up the game to see the results are very nice. This technique also works with spritesheets, although the script to compile the spritesheet has to wait for all the images to be rendered before compiling the final image.

This is all free, open source software. The Blender file, the game, and the Anura engine can be found over on github. If you’d like to get started using our shiny engine, drop us a note on the forums or talk with us via internet relay chat.

An early beta of Cube Trains is available from http://ddr0.github.com/.

FacebooktwitterredditmailFacebooktwitterredditmail

Graphics News #20

August 26th, 2012 by Jetrel

We’ve done a total overhaul of the forest ground tiles, similar to what was done to the cave tiles. In these screenshots you’ll also see the new foreground art, some minor enhancements to the background, and a third palette used in the forest. There’s also a much-needed overhaul of our old, ugly fountain art, which now meshes nicely with the level tiles.

FacebooktwitterredditmailFacebooktwitterredditmail

Making some friends

July 1st, 2012 by Jetrel

I’ve decided to occasionally link to other indie/semi-indie games I’ve been playing and enjoying, just to share the love. Reciprocity would be cool, but honestly I wouldn’t be surprised if quite a few of these people don’t even notice the linkage. I’m just doing this for the good of the indie game scene.

This might seem odd, but I’m really not afraid of “competition” – I don’t think other indie games would stop people from playing Frogatto. The cost isn’t exclusionary on mobile games, the time taken by story-driven games leaves you with plenty of time to play the others, and I just think there’s so much more to be gained by cooperation. There’s a short supply of really well-made indie games, and I want to see our art form thrive – I want to see other teams, who’ve put their heart and soul into it, succeed.

Pizza Boy:

So the first one is a game I’ve been playing on my iPod called Pizza Boy, which is a platformer, but is really, really different from Frogatto in almost every way. It’s very much in the Mario Bros vein of things – rather similar physics, timed-levels, worlds with four stages, and a lightly-handwaved story. It also shares the mario trope of killing enemies by jumping on their heads (which we use somewhat sparingly in frogatto).

Pizza Boy is made by Acne Play, an offshoot of a Swedish design studio which seems to be increasingly branching into game development. (No, we don’t know these guys personally or anything.)

The whole game is built around some pretty tight platforming challenges, where each level is an exacting sequence of running and jumping sequences you have to figure out by trial and error, and then play back with crackerjack timing (quite unlike frogatto, which generally allows you to stop and smell the roses). Unlike mario, it’s quite forgiving because you can start at any level you’ve been on before (which probably defeats the purpose of having ‘lives’, but there they are anyhow). I like it – it’s frustrating, but frustrating in a good way.

One thing that’s great about it is a common mobile-game trope – there’s not much you have to remember (as you would in a complex, story-driven game like an rpg), so it’s really easy to get into if you’ve got a few minutes to kill. You don’t have to re-familiarize yourself with some big complex set of info (like, say, which items you’ve acquired, or which quest you’ve completed). I know from personal experience, that this can be a bit of a bugaboo if you haven’t played a game for several days or weeks (I definitely have had at least one RPG I’ve entirely started-over because I lost track of what I’d accomplished). I don’t wish all games were like this, but it really is nice for some games to be immediately accessible.

Also interesting to see another title doing the Left/Right controller scheme, rather than a full virtual Dpad. Seems to be gradually becoming an accepted/best practice for these kinds of games. We adopted it quite a while back (I believe sooziz was the title that inspired us to do so), because having up/down arrows between L/R, or having a full, plus-shaped dpad makes your touch areas for the side keys way smaller, and especially the U/D between L/R setup makes it possible to hit up or down by accident when “hat-switching” over to the opposite side – in a lot of games, this can really trip your character up.

So there’s Pizza Boy. Check it out!

FacebooktwitterredditmailFacebooktwitterredditmail

Graphics News #19

June 21st, 2012 by Jetrel

A showcase of a whole mess of things we’ve been working on for the dungeon in the coming update. The dungeon has doubled in size, and best of all, the dungeon level-tree is now non-linear (an improvement I’m hoping to eventually have on most chapters of the game).

There are a wealth of graphical improvements; the back-wall in the dungeon now has actual edges, and windows, so we can crumble it away and reveal background art. Background art was also something we were lacking before; we now have two different parallax backgrounds where we previously had none. The whole dungeon has also been quietly switched to a perspective matching the rest of the game (a subtle change we began around 1.2 which we feel looks much better – the only holdout remaining is the seaside interiors which I’ll redo later).

Last but not least, we also have a bunch of different palettes in the dungeon which help set the mood in different areas.

FacebooktwitterredditmailFacebooktwitterredditmail

A Gentle Introduction to Frogatto Formula Language

May 25th, 2012 by Sirp

Frogatto Formula Language (FFL) is the language used to customize Frogatto and control its behavior. I’ve talked about how Frogatto’s event handling system works before, right here.

Today I’m going to talk more about how FFL works, giving an overview of the language.

Getting Started

Becoming familiar with FFL is easy. Just start Frogatto and press ctrl+d to enter the debug console. The debug console allows you to type FFL statements and have them evaluated right then and there. Try some basic commands:


--> 4 + 5
9
--> 7*3 + 9
30
--> 7*(3 + 9)
84
-->

Accessing an Object

When an FFL formula is executed, it has an object it is operating on. When you first open the debug console, that object is the player. Let’s try some basic formulas that find information about the player:


--> x
416
--> y
383
--> type
'frogatto_playable'
--> animation
'stand'
-->

Frogatto debug console

You can output the entire player object by entering self as a command — it will show you all the fields the player has to offer!

Where Clauses

For convenience, FFL supports where clauses that appear at the end of an expression to define additional values:


--> 2*n + n*n where n = 5
35

Object Mutation

So far we’ve seen how to query the values from an object. If you enter a formula that returns a command, the debug console will execute the command on the object. It might be a good idea to pause the game, by pressing ctrl+p before executing commands, so you can clearly see what’s going on.

Let’s try executing some commands:


--> set(y, y-250)
(0xaebeb30) {}\
--> set(facing, 1)
(0xaebec80) {}
--> set(upside_down, true)
(0xafbed90) {}
-->

Frogatto upside down!

Remember, what you are executing here in the debug console is the same kind of thing you would execute in an event handler when it is executed.

When the debug console is open, you can click on objects to select them, and they will become the focused object — they will be the context of any formulas you enter. For instance, you could click on a door, and then start typing commands to modify it.

Basic data types

As we’ve seen, Frogatto can handle manipulation of integers. You may have noticed it also supports strings. e.g.


--> type
'frogatto_playable'

Strings can be concatenated, just as integers can be added:


--> 'abc' + 'def'
'abcdef'

You can also multiply a string by an integer:


--> 'abc' * 4
'abcabcabcabc'

Other types, such as integers, can be concatenated to a string using +:


--> 'you have ' + 5 + ' coins'
'you have 5 coins'

FFL also supports decimal numbers:


--> 4.25 * 0.3
1.275
--> 10.8 + 5
15.8
--> -0.5 - 0.8
-1.3

FFL decimals are not floating point numbers. They use fixed point arithmetic and store up to six decimal places. Their behavior is consistent across machines.

FFL also supports the boolean types, true and false as well as the value null to represent no object.

Basic Operators

FFL supports the following basic operators:

  • + – * /: arithmetic operations
  • and or not: boolean operators
  • %: modulo operator. e.g. 9%8 -> 1
  • ^: exponentiation operator. e.g. 2^8 -> 256
  • = != <>=: comparison operators

Note that unlike many languages, = is used to test for equality, as FFL doesn’t have built-in assignment. Assignment is done by returning a set() object from a formula, requesting the game engine to perform the equivalent of an assignment.

Random Numbers

FFL supports random numbers using the d operator:


--> 3d6
5
--> 3d6
11
--> 3d6
12
--> 50d100
2613
--> 3d faces where faces = 10
12
--> ndice d faces where ndice = 3, faces = 6
16

Functions

FFL has a wide range of built-in functions. A function is executed using function_name(parameters). A fundamental function is the if function:


--> if(2 < 4, 1, 2)
1
--> if(2 > 4, 1, 2)
2

if tests the first parameter and if it’s true, it will return the second parameter, otherwise it will return the third parameter. The third argument is optional, and will be null if not provided.


--> if(1 > 2, 5)
null

There are also functions to convert values from one type to another, or test the type of a value:


--> str(4)
'4'
--> is_int(4.2)
false
--> is_int(4)
true
--> is_string('abc')
true
--> is_string(4)
false
--> floor(4.2)
4
--> ceil(4.2)
5
--> round(4.2)
4

Lists

FFL supports lists which are enclosed in square brackets:


--> [5, 2+4]
[5, 6]

Lists can be appended using the + operator:


--> [3, 5] + [7]
[3, 5, 7]
--> ['hello', 'there'] + [5, true, [4, 5]]
['hello', 'there', 5, true, [4, 5]]

Note how lists can be nested. i.e. you can have lists of lists. Lists can be multiplied just like strings:


--> [1, 2, 3] * 3
[1, 2, 3, 1, 2, 3, 1, 2, 3]

A single element of a list can be accessed using square brackets:


--> a[2] where a = [1,2,3,4]
3

You can also take a slice of a list using [begin:end] after the list:


--> a[2:5] where a = [1,2,3,4,5,6,7]
[3,4,5]
--> a[1:] where a = [1,2,3,4,5,6,7]
[2,3,4,5,6,7]

You can find the number of elements in a list using the size() function:


--> size(a) where a = [1,2,3]
3

Lists can be compared using = and != operators, and also using the relational operators,=. For instance,


--> [2,3,4] < [5,6]
true
--> [2,3,5] false

You can find if an item is in a list using the in operator:


--> 3 in [2,3,4]
true

Functions for Operating on Lists

FFL supplies a range of functions for operating on lists. One such function is the map function:


map(list, expression): evaluates expression once for each item in list, giving 'value' as the name of the item.

This is perhaps best explained with an example:


--> map([1,2,3,4], value*value)
[1, 4, 9, 16]

Note how the expression value*value is evaluated once for each item in the list, with value containing that item. One thing that might seem strange to experienced programmers is how the parameter passed to the function is not eagerly evaluated, but rather, the function chooses when to evaluate it, and even what context to evaluate it in.

The map function can take an additional argument specifying the name of the parameter, to something other than value. For instance,


--> map([1,2,3,4], n, n*n)
[1, 4, 9, 16]

The range function is useful for generating a list of integers:


--> range(10)
[0, 1, 2, 3, 4,5, 6, 7, 8, 9]
--> range(5, 10)
[5, 6, 7, 8, 9]

The range function is often useful to produce a list to pass to map.

The filter function is useful for taking certain elements of a map that pass a certain criteria:


filter(list, expression): evaluates expression once for each item in list, and returns a list of all the items for which the expression was true.

For instance,


--> filter(range(10), value%2 = 1)
[1, 3, 5, 7, 9]

Map + Filter + Range: Example

The spawn function can be used to create an object. For instance, spawn('coin_silver', x, y-80, 1) will create a silver coin 80 pixels above Frogatto’s head. Let’s suppose we wanted to create ten coins in a row, we could do this:


--> map(range(10), spawn('coin_silver', (x - 200) + value*30, y - 80, 1))

This will create a list of 10 spawn commands, creating 10 coins spaced out above Frogatto’s head.

Now suppose we wanted to move all these coins up by 20 pixels. level.chars holds a list of all the objects in the level. We could filter by type to find all the coins in the level, and then use map to map these objects to set commands:


--> map(filter(level.chars, value.type = 'coin_silver'), set(value.y, value.y - 10))

This will move all silver coins in the level up 10 pixels.

List Comprehensions

Frogatto supports a convenient way to build lists, known as list comprehensions. Let’s start with an example:


[n^2 | n <- range(10)] = [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

This is equivalent to saying "for each n in range(10), generate a list with n^2". A list comprehension can also contain filtering conditions on the input list. For instance, if we wanted to square only even numbers, we could do this:


[n^2 | n <- range(10), not n%2] = [0, 4, 16, 36, 64]

A list comprehension can take multiple input lists, in which all the combinations of elements in each list are used. For instance:


[a + ' ' + b | a <- ['small', 'big', 'huge'], b <- ['ant', 'bird', 'bat']] = ['small ant', 'big ant', 'huge ant', 'small bird', 'big bird', 'huge bird', 'small bat', 'big bat', huge bat']

List comprehensions are a convenient alternative to using map and filter. This formula from earlier can be re-written using list comprehensions:


map(range(10), spawn('coin_silver', (x - 200) + value*30, y - 80, 1))

As a list comprehension:


[spawn('coin_silver', (x - 200) + n*30, y - 80, 1) | n <- range(10)]

Dictionaries

FFL supports dictionaries, also known as maps. A dictionary is a series of key:value pairs written within curly brackets. For instance,


--> {y: 5, x: 2}
{'x': 2, 'y': 5}

Note how the keys are assumed to be strings, rather than x and y being interpreted as expressions. Also, keys in a map are always sorted.

Any FFL type may be a key in a map. Integers, booleans, lists, and even other maps are valid keys:


--> {[3,4,5]: 7, {a: 5}: 9}
{[3, 4, 5]: 7, {'a': 5}: 9}

Elements in maps can be looked up either using the . operator, or using []:


--> a.name where a = {name: 'Frogatto'}
'Frogatto'
--> a['name'] where a = {name: 'Frogatto'}
'Frogatto'

The . operator only works on string keys that are valid identifiers (a valid FFL identifier begins with a letter or underscore and consists of letters, underscores, and digits). The [] operator can be used for all types of keys.

Objects

FFL supports objects as data types. An object looks and behaves similar to a dictionary, however an object may have additional behavior or properties to a regular dictionary. FFL doesn't have support for directly creating objects, but an FFL formula might be given access to an object, or have an object returned by a function.

One example of an object is the game object that represents Frogatto. When you start the debugger, you have access to the player's game object. That is why you can enter a formula such as x or y or type and see a result. The level itself is exposed as an object, and all objects have access to it through their level property.

Another example of objects are command objects. Command objects are created and returned when you call a function like set() or spawn(). These types of objects don't actually have any interesting values that can be queried from FFL. That is why you see a result like this:


--> spawn('coin_silver', 10, 10, 1)
(0xb825640){}

This formula returns a spawn command object, but the contents of the object are opaque to FFL, so all FFL knows about it are the address and then has an empty {} properties map. FFL doesn't need to know how to query or manipulate a command object though, since the entire idea is to return it to the game engine, and the game engine knows how to execute the command and make the object get spawned.

This is a general tutorial on FFL, so I'm not going to get too into the different types of objects available. The crucial thing to understand, though, is that FFL is a pluggable language that can be used in different contexts. The most common use for FFL right now is to write Frogatto event handlers with, however it's designed to be used in different contexts -- we also use it to write editor scripts with, gui scripts, and scripts to manipulate FSON documents. Depending on how and where you use FFL you will have access to different types of objects.

Functions

You can define your own functions in FFL:


--> def f(n) n^2 + 5; f(5) + 2
32

Functions are themselves variables that can be passed to functions and otherwise treated as regular values. For instance,


--> def f(fn, x) fn(5, x); def add(a, b) a + b; f(add, 2)
7

Note: Built-in functions currently cannot be treated as values or passed around. We are looking to fix that in a future release.

Functions can have default arguments specified:


--> def f(a, b=5) a+b; [f(1,1), f(2)]
[2, 7]

Recursion

Functions can call themselves. As an example, suppose you wanted to write a function index(list, item) -> returns the index of the first occurrence of item in list, or -1 if item is not in list

you could do it like this:


def index(list, item, n=0) if(list = [], -1, if(list[0] = item, n, index(list[1:], item, n+1)))

As another example, FFL has a builtin sort() function, but if you wanted to make your own sort, you could implement quicksort like this:


def qsort(list) if(size(list) qsort(filter(list, value < pivot)) +
filter(list, value = pivot) +
qsort(filter(list, value > pivot))
where pivot = list[0])

True or False?

At certain times, FFL will test whether a value is considered 'true' or 'false'. The following values are considered false:

  • false
  • null
  • 0
  • 0.0
  • []
  • {}

All other values are considered true. Note that the and and or operators have particularly interesting behavior: or will evaluate to its first argument if its first argument is a true value, otherwise it will evaluate to its second argument. Likewise, and will evaluate to its first argument if its first argument is a false value, otherwise it will evaluate to it second argument.


--> 5 or 2
5
--> false or 8
8

Wrap-Up

I hope this FFL overview has been helpful. Please post any feedback or comments below!

FacebooktwitterredditmailFacebooktwitterredditmail

Developing Games using the Frogatto Engine: Part 3

May 15th, 2012 by Sirp

For part 3 of the tutorial on developing a game with the Frogatto engine, I’ve decided to do a series of videos demonstrating how to add walking, jumping, and crouching to Elisa. I recommend watching the videos in as high resolution as you can. Here are the videos:



 

+ Recommended Reading
→ Next Page
Table of Contents
Previous Page

FacebooktwitterredditmailFacebooktwitterredditmail