Working with cameras in CraftStudio

This tutorial will teach you some of the (simple) maths behind the relations between the textures pixels, the screen pixels and the scenes units in CraftStudio.

You will learn how to convert from units to pixels for both orthographic and perspective cameras in order to know if a game object is visible from a camera or where it appears on the screen.

Some definitions :

  • su : scene units
  • tpx : texture pixels
  • px : screen pixels
  • SSS (Smallest Screen Size) Size in pixels of the smallest side of the screen (usually the height)
  • frustum : the world space that is seen by a camera (you see an objet only when it is inside a camera’s frustum). In the scene editor, frustum boundaries are marked by grey outlines going from the camera’s game object :

Frustums of an orthographic (left) and perspective camera (right)

Texture pixels

The base relation between texture pixels and scene units is : 16 tpx = 1 su.

Size of an object in the world

All relations are for a single axis.

Models

Given a single model block :

Size (su) = block size (tpx) / 16 * stretch * game object scale

Maps

For a single map block :

Size (su) = tile size (tpx) / 16 * game object scale

Get the tile size with tileSet:GetTileSize().
The size in each axis also depends on the block’s shape.

Fonts

Size (su) = text width (su) * game object scale

Get the text’s width with textRenderer:GetTextWidth(). The returned width is always the width when the game object has a global scale of 1.

This is for the width only (the game object’s local X axis).
The height depends on the font’s characters height (and the game object’s scale on the Y axis). There is no way to get this data via script but it will most likely be 1.5 * character width.

Orthographic cameras

The orthographic scale is the size in scene unit of the smallest side of the screen.

orthographic scale (su) <=> SSS (px)

Continue reading

Daneel v1.4.0 is out

It’s already time for a new version, Daneel v1.4.0 is out !
A few new features, but nice improvements.

The two most notable new features are the Draw object that introduce the LineRenderer and CircleRenderer components, as well as the capacity to easily add error reporting and stacktrace to any functions (without modifying or overloading them yourself).

All functions that extends Lua’s built-in library are now in there own file and completely independent from Daneel. You can use this file in any of your project !

Using Daneel in the webplayer in now a lot simpler since all you ave to do is use the provided player.html file.

The documentation layout has also been revamped to be even more cleared.

DownloadDocumentation

Here is the full changelog :

Continue reading

How to create an in-game chat with CraftStudio and Daneel

It’s always cool to be able to chat with fellow players while playing a multiplayer game.
This tutorial will guide you through the creation of such in-game chat with CraftStudio and Daneel.

In the course of this tutorial, you will also learn :

  • About Daneel’s tags, events and dynamic getters and setters calls
  • How to setup buttons with Daneel and the Mouse Input script
  • How input fields works
  • How to setup a basic server and connect to it

But first let’s think about what we need :
The chat will use CraftStudio’s networking API, so we need a way to :

  • create a server
  • connect to the server
  • store the player ids of the connected players
  • one script to handle all that

Then for the chat itself, we need to be able to write in an input field as well as display text, plus the chat script itself.

Project setup

Download the tutorial’s .cspack or connect to the tutorial’s project.

Create a new project, select the .cspack in the Import/Export tab of the project’s administration then import the four scripts Daneel, Mouse Input, GUI/GUI and GUI/Input as well as the Calibri font (you are free to use any other font).

Setup the LeftMouse and RightMouse game controls.

Create two additional textual scripts : Scene Manager and Chat.

Create a scene.
Add a game object named Daneel (for instance) then add both scripts Daneel and Scene Manager as a scripted behavior. Keep this game object at the top of the hierarchy.
Add another Camera game object, add a Camera component and set it to Orthographic then add the Mouse Input script as a scripted behavior.

Continue reading

Crafting Minecraft in CraftStudio: the Tutorial

I started a series of tutorials that aims to build a Minecraft-like with CraftStudio (and Daneel). You can read them at :

http://minecraft.florentpoujol.fr

If you have CraftStudio installed, you can also join the project where the assets created during the tutorials are hosted (the link will open the project in CraftStudio’s client if it is installed on your computer, or do nothing).

The whole tutorial is completely WIP, even chapters that you can already read. So if you have any feebacks, unanswered questions, complains about how I write bad english, etc, I will be happy to hear from you !

minecraft_tutorial_logo

Current chapters are :

For those interested, the sources are hosted on GitHub.

Markdown Static Site, easily turn markdown files in a static site

Markdown is a file format and concise syntax whose first intent is to be converted to HTML. Today, you have tools to convert markdown in a wide variety of other formats

Because of that, I wrote Daneel’s documentation as well as several upcoming tutorials (more on that soon !) in markdown and I needed a simple way to setup a proper site from these markdown files.

I emphasized “simple” because Daneel’s documentation currently uses the docs bundle of the PHP framework Laravel 3.5. It works like a charm and does exactly want I need but it’s seriously overkill to just browse a bunch of static files !

That’s why I created just a small vanilla PHP script that lets you easily turn a bunch of markdown files into a static site. Basically, all you have to do is access the files through their path and voilà. It supports url rewriting as well as ommitting the .md extension in the url out-of-the-box.

Feel free to fork/share/do whatever you want with it !

My Global Game Jam 2014 entry is a Karkass

Karkass is the game I made with 7 other wonderful people of the CraftStudio comunity during the 48 hours of the Global Game Jam 2014, at the Nancy gathering. It is about controlling octopillars trying to escape a deadly turtolosaurus skeleton or fight it with fruits in an enchanted forest.

karkass_featured2Deep in the enchanted forest, four octopillars are playing around when they stumble upon the skeleton of the legendary turtolosaurus, Karkass. As one of them revives the giant corpse, it becomes drunk with power and hunts the others down. Grab fruits and throw them at Karkass before it gets you. Avoid the traps and use the terrain to your advantage: Karkass is huge and won’t be able to follow you through the smallest areas. Take control of the skeleton yourself and smash the other players to score the most points. Local multiplayer – up to 4 players using Xbox 360 controllers. Karkass was made together by 8 people using CraftStudio, the cooperative game-making platform.

This year’s theme (the sentence “We don’t see things as they are, we see them as we are.”) wasn’t very much appealing for anyone of us, so we quickly set out to create a game about local multiplayer.

You can play it from two to four players, with xBox 360 controllers or the keyboard. There is two maps to play, the arena and a soccer field, but the soccer mode is still unfinished/a little buggy (scores don’t work, for instance).

With a team composed of 3 programmers, 4 artists and a game designer, we managed to create CraftStudio’s most visually advanced game to date ! And that wasn’t for nothing since the local jury awarded us with the first place (of the 17 other games made at this location) !

Check out karkass’s Global Game Jam page (with download links)

karkass01karkass02 karkass03karkass_soccer

Daneel 1.3 is out !

Hi everybody !

Already 5 months have passed since the last release of Daneel, my framework for CrafStudio. So it was really about time for me to get the next version out.

So what’s new ? Well, no big new functionality this time, but a lot of improvements and adjustments everywhere in the code. One of the biggest improvement is that it now fully works with CraftStudio’s Web Player. But be sure to read thoroughly the setup page if you target your game for the web player, though.

I think this version definitely brings more consistency, more robustness, is more useful, has less bug and is more user-friendly.

DownloadDocumentation

Check out the changelog below :

  • Core :
    • Merged files Daneel, CraftStudio, GameObject, Lua and DaneelBehavior into the single file Daneel.
    • Added Daneel.Utilities.ButtonExists(), Daneel.Debug.Try(), Daneel.Cache.GetId(), Daneel.Storage.Save() and Daneel.Storage.Load().
    • Removed Daneel.Utilities.GetValueFromName(), Daneel.Utilities.GlobalExists() (they are replaced by table.getvalue()).
    • Added persistent listeners, replaced Daneel.Event.Clear() by Daneel.Event.StopListen() called without the event name argument. Removed scheduled events : Daneel.Event.FireAtRealTime(), FireAtTime() and FireAtFrame()
    • Hotkeys now work without setting anything in the config, just listen to the events.
  • Extension of Lua’s built-in libraries :
    • Added math.lerp(), math.warpangles(), math.round(), table.getvalue(), table.isarray(), table.reverse(), table.shift() and table.reindex().
    • Updated string.split() so that it can use a Lua pattern as delimiter. The third argument has changed : it now tells if the delimiter must be considered as a pattern or plain text (the default).
    • Renamed table.length() in table.getlength(), table.compare() in table.havesamecontent().
    • Removed string.isoneof() and table.new().
  • Extension of CraftStudio’s API :
    • Added Asset.GetName(), Asset.GetId().
    • Added ModelRenderer.Set(), MapRenderer.Set(), Camera.Set(), Camera.SetProjectionMode()
    • Updated some asset setters to accept nil as argument : SetModel(), SetModelAnimation(), SetMap(), SetFont().
    • Allowed ray:IntersectsModelRenderer(), ray:IntersectsMapRenderer(), ray:IntersectsTextRenderer() and ray:IntersectsPlane() to return a RaycastHit instead of a serie of values if the third argument is true.
    • Scene.Load() or CS.LoadScene() now set the current scene asset as the value of the Scene.current property.
    • Game objects :
      • Updated GameObject.New() to also do the work of GameObject.NewFromScene() which has been removed.
      • gameObject:SendMessage() now fails gracefully if an error happens inside the function called and displays info about the game object, message name and data passed as argument.
      • Updated gameObject:AddComponent() to also do the work of gameObject:AddScriptedBehavior() which has been removed.
      • Added gameObject:GetTags().
  • Triggers :
    • Added Trigger:IsGameObjectInRange(), removed arguments to Trigger:GetGameObjectsInRange() and renamed the checkInterval property in updateInterval.
    • Triggers may now use the shape of a model or a map in addition to the distance-based sphere.
  • Mouse Input :
    • Renamed MouseInputs script in Mouse Input. Renamed the workInterval property in updateInterval.
  • Lang :
    • The Lang object is now a first-level global variable (Daneel.Lang doesn’t work any more).
    • Moved Lang object into its own script that can also be used as a scripted behavior. Language functions must now be nammed Lang[language name]().
  • Tween :
    • The Tween object is now a first-level global variable (Daneel.Tween doesn’t work any more).
    • Added the updateInterval property for tweeners.
    • Added the Tweener and Timer scripted behaviors.
  • GUI :
    • The GUI object is now a first-level global variable (Daneel.GUI doesn’t work any more).
    • Added Vector2.GetLength() and Vector2.GetSqrLength()
    • Added GUI.ToSceneUnit(), GUI.Hud.ToPixels(), GUI.Hud.FixPosition().
    • Allowed position of GUI.Hud to be set in percentage or relative to the screen sides size.
    • GUI.Sliders now position themselves vis-à-vis of their parent game object. GUI.Sliders and GUI.Toggle don’t require their scripted behavior to work properly any more.
    • GUI.Input may now be focused via a background model and have a cursor.
    • Renamed GUI.ProgressBar.*Progress() functions and the progress property in SetValue(), UpdateValue(), GetValue() and the value property.
  • Introduced the notion of Core vs Modules and separate user configuration for the core and each module : DaneelUserConfig() and [Module name]UserConfig().
  • Fixed many bugs, improved a lot of code and ensured that Daneel fully works in the webplayer.

CraftStudio Toolbox

Florent’s Toolbox is a CraftStudio project that contains several assets I found interesting to share.

There are mostly scripts, which are usually independent from each other (some comes from Daneel but were modified to be “standalone”).

You can try to look for the Florent’s Toolbox project on the Community Projects in CS or download the project from this link. You can also check the GitHub repo.

Here is what it contains for now :

Scripts

  • Camera Control (Move and rotate the camera around)
  • Frustrum Culling (Interact with game objects that enter or leave the camera’s view)
  • Mouse Input (Make the mouse interact with game objects)
  • Spawner (Spawn game objects repeatedly)
  • Timer (Do something when the time’s up)
  • Trigger (Interact with game objects that are within a certain range of the trigger)
  • Event
  • Lang (Localize strings) (also a scripted behavior)
  • math
  • string
  • table
  • Tags (Categorize game objects) (also a scripted behavior)
  • Utils (Some utilities functions)
  • Vector2 (Like Vector3, but with x and y only)

Fonts

  • Calibri

CraftStudio Script Handler

With Daneel, I often needed to copy several large scripts from their .lua file over to CraftStudio and it took several seconds per script every times. I really needed a way to do that automatically.

So I created an application that can basically convert Script assets from CrafStudio (.csscript files) to regular Lua scripts (.lua) and vice-versa.

The app can read a CraftStudio project and create a .lua version of all of the project’s scripts. The opposite is also possible : read a bunch of .lua scripts and overwrite the corresponding Script assets in a CraftStudio project.

The use case is very specific and it’s not super practical as you need to stop the local server to write in a CS project, but that’s what I share here.

The app is created with Unity3D, so it should works on Mac and Linux too. You can download the app from there and the source is available on my GitHub account.

If you planned to create such external application that deal with CraftStudio files, you may be interested by the ProjectFileHandler class that reads the Projet.dat file and extract data about the project, the game controls and especially the assets (id, type, name, revisions names).

The ScriptFileHandler class deals with a particular Script asset and its revisions. This is where the conversion from .csscript to .lua and vice-versa happens.

Multiplayer Pong with CraftStudio

In order to test the multiplayer networking and create my first ever multiplayer game, I did a small two-players Pong with CraftStudio. You can access the project through this link or search for Multilayer Pong via the “Community Projects” in CraftStudio. You can also download the project from this link.

YouTube Preview Image

I didn’t show it in the video but you can edit the IP you connect to. You can also play solo and switch the paddle you control (the red one) by pressing the space bar.

The project is really basic, I just took the code from Blast Turtle and adapted it to my style and the needs of a game like Pong.

I am done with the project but if you want to improve over it, just ask me so that I give you member role in the project.

You can discuss the game on the community’s forums : http://www.craftstudioforums.net/index.php?threads/multiplayer-pong.1424/

Mini-Galcon Post-Mortem

Min-Galcon is the first of a series of mini games which aims to reproduce the basics mechanics of existing games and experiment with CraftStudio.

You can access Mini-Galcon’s project by searching for it in the community projects in CraftSudio. You can also download it from Daneel’s website.

For those who don’t have CraftStudio, you can at least download the game for Windows.

So here are some of the tricks used while building Mini-Galcon.

Using Font as sprite sheet

The Font asset is basically a sprite sheet, a collection of images. It has been built specifically with the TextRenderer component to display text but nothing prevents you to to use it for anything else. It has the advantage (over the models) to use a single asset for multiple colors/sizes/forms.

Since the planets and the ships are flat, that’s what I used for the planets (See the Planets font). I used models for the ships for the reason you will discover below.

Main Menu

Thanks to the newly released Daneel’s GUI components, the level of interactivity provided by the main menu is pretty high compared to the amount of code needed to implements it (see the MainMenu script).

Toggle component

    -- player colors = team
    local colors = GameObject.Get("Colors").children

    for i, colorGO in ipairs( colors ) do

        colorGO.toggle.OnUpdate = function( toggle )
            if toggle.isChecked == true then
                toggle.gameObject.transform.localScale = 1.5
                local modelPath = Asset.GetPath( toggle.gameObject.modelRenderer.model )

                Game.playerTeam = tonumber( modelPath:sub( #modelPath ) )
            else
                toggle.gameObject.transform.localScale = 1
            end
        end

        if i == (Game.playerTeam - 1) then
            colorGO.toggle:Check( true )
        end
    end

You can select your ship’s color with three radio buttons which are toggle components that are in the same group, so that only one of them can be checked at a time and clicking of a non checked toggle automatically unchecked all other toggles.

In the OnUpdate event (called when a toggle is checked or unchecked), the scale of the model is changed to reflect its state and the player’s team is set based on the model’s name (which ends by the team number).

Asset.GetPath(asset) is mostly an alias of Map.GetPathInPackage(asset) which returns the fully-qualified path of the provided assets (works for any asset, not just Maps !).

Input component

    -- level's number of planet
    local planetCountGO = GameObject.Get("PlanetSelection.Input")

    planetCountGO.textRenderer.text = Game.planetCount

    planetCountGO.input.OnFocus = function( input )
        if input.isFocused then
            input.gameObject.child.modelRenderer.opacity = 0.5

        elseif not input.isFocused then
            input.gameObject.child.modelRenderer.opacity = 0.2
            if input.gameObject.textRenderer.text:trim() == "" then
                input.gameObject.textRenderer.text = "10"
            end
        end
    end

Here GameObjet.Get() is used first to actually search for a hierarchy of objects and returns the last specified child.

When the input gain or lose the focus, its background’s opacity is changed to reflect the new state. The child property on the gameObject is a shortcut for the GetChild() function without argument which returns the game object’s first children (in this case the game object with the background model).

Slider component

    local go = GameObject.Get( "AIDifficulty" )
    local sliderGO = go:GetChild( "Handle", true )

    sliderGO.slider.OnUpdate = function( slider )
        Game.difficulty = math.floor( slider.value )
        go.child.textRenderer.text = "Difficulty : " .. Game.difficulty
    end

    sliderGO.slider.value = Game.difficulty

Another great way to let players set a value within boundaries is to use a slider they just have to moves with the mouse. It requires minimum setup via its scripted behavior and when the slider is updated (moved), the game’s difficulty is set and the value of the text next to the slider is updated accordingly.

Play button

    local playButton = GameObject.Get( "PlayButton" )
    local t = Daneel.Tween.Tweener( playButton.transform, "localScale", Vector3( 0.1 ), 0.8, {
        isRelative = true,
        loops = -1,
        loopType = "yoyo"
     } )

     playButton:AddTag( "button" )
     playButton.OnClick = function()
        Game.planetCount = tonumber( planetCountGO.textRenderer.text )
        Scene.Load( "Level" )
     end

Creating a button requires no more than three steps :

  • set a tag on the button.
  • set the OnClick event on the button.
  • make sure the tag is also set in the tags public property on the MouseInput scripted behavior added on the camera the button is visible from.

The “Heart Beat” animation is produced by the infinite looping tweener that offset the button’s scale by 0.1 over 0.8 second.

Generating the level

The level you play is randomly generated based on the number of planets you choose with the input field. See in the Awake() function in the GameManager script.

Based on the number of planets, a square is defined, inside which the planet’s positions are randomly picked (in addition to the planet’s scale and number of ships it holds). The position is then checked to see if it is not too close to a planet that already exists.

The script also keep track of which planet is at the top and  the bottom of the level. This is those planets who will become the planets the player and the AI start the game with. Once all planets are spawned, the team of both planet is set (the other planets are neutral) and their scale and ship count are made equal (for equity, because the scale impact the rate at which a planet produce ships).

AI

“Dumb automaton” would be a more appropriate term but let’s use AI anyway. The only thing the AI really does is that it picks one of its planets with enough ships and sends them to the nearest neutral or enemy planet, every time it is allowed to take a decision.

The game difficulty (which you select via the slider in the main menu) impacts two settings of the AI : the interval at which it is does something (sends ships to another planet) and the ship threshold or minimum number of ships a planet must have to be “used”. The smaller the difficulty, the smaller both values are.

A difficulty of 1 leads to a very reactive AI that spread quickly but may be easy to conquer since none of its planets holds more than a couple of ships. It is to your advantage on a small level where you can conquer its few first planets quicker than it spread but on a big map, it may have already conquered several planets by the time your ships arrives to its side of the level. Once it has conquered a few more planets, I became really hard to take the advantage back since the AI uses all its ships on all of its planets way faster than you -weak human- can do it.

On the other hand at higher difficulty, the AI tends to have fewer planets but that are harder to conquer because it takes decision less often and have a higher ship threshold. In this case however, you can easily spread faster than the IA and finally overwhelm it with ships.

Selection box

A selection box appear when you left click and drags the mouse in the level, this allows you to select multiple planets.

The selection box is just a model in front of the camera (between the camera and the planets) that is scaled depending on the distance between the location of the mouse when the left click first happened and the current mouse position. This also works because the selection box model is 16 model units wide and its origin has been moved to the upper-left corner of the box and its  game objet has a scale of 1.

Now to detect if a planet is inside the selection box when the left click is released, a ray is created between the camera and the planet. The planet is inside the selection box if the ray also intersects the selection box’s model renderer. (I didn’t tried it yet but this is how I would implement some frustrum/occlusion culling).

Lots of ships !

The planets increase their ship count at a rate based on their scale and spawn their ships (one per frame) when asked to. The ship count on a planet also varies when ships arrive at it, depending on the team of the ships. Same team increase the count, different team decrease the count until it reaches 0 and the planet changes team. The ships just move from one planet to another.

That was the occasion for me to experiment with the performances related to moving a several hundred or thousand of game objects (rendered on screen with a model).

First, be aware that using transform:Move( offset ) is way faster than getting the old position and manually setting the new position ( transform:SetPosition( transform:GetPosition() + offset ) ). Obviously the number of times a second you update the position also has an impact on the performance. Here is a benchmark below.

The number is the approximate number of ships at which the game begins to slow down (the movement of the ships starts to appear jerky) on my computer (Scientific Process Inside).

Using transform:SetPosition()

  1. function called every frames : 440
  2. function called every 2 frames : 750
  3. function called every 3 frames : 950

Using transform:Move()

  1. function called every frames : 760
  2. function called every 2 frames : 1280
  3. function called every 3 frames : 1500

Now the issue is that you can’t just makes the ships move every 10 frames for instance because the movement appears jerky as soon a couple of frames between each movement. It’s probably not necessary for Mini-Galcon unless you have a big level but I wanted to find a way to have even more ships moving at the same time :

In CraftStudio there is only two ways to get something moving : moves the game object or moves a model block via a ModelAnimation. That’s why models are used for the ships. The ships use a looping animation that moves the only ship’s block forward. Since the animation last 0.5 second, the game object itself is moved only every 30 frames and at the same frame where the animation restart, so the movement appear “normal”, yet the game object only moves twice per second.

And since the ModelAnimation are handled by CraftStudio, and not the Lua scripts, they are faster and allows -in my benchmark- to have more than 2500 ships moving at the same time without noticing major performance issue !

Daneel v1.2.0 is out !

Hey everyone !

Daneel came a long way since its beginning and today’s release adds a ton of new features.

I didn’t planned to wait that long to release a new version but cool features kept popping in my head, for the best.

So here are some of the major new features (you can also read the full changelog) :

GUI components

GUI components allows to easily create classic structures for user interaction as check boxes, radio buttons, progress bar, slider, input field and multiple line text.

Mouse interaction with game objects are also really easy to setup.

Tweeners

They are objects that interpolate a value (or the property of an object) overtime, optionally using an easing equation.

They can be used to create anything from animations (great for menus) to timers.

Localization

It’s super easy to setup texts that depends on the user’s language.

    function DaneelLanguageEnglish()
        return {
            greetings = {
                welcome = "Welcome :playername !",
            }
        }
    end

    function DaneelLanguageFrench()
        return {
            greetings = {
                welcome = "Bienvenu :playername !",
            }
        }
    end

    -- get the lines in the current language :
    Daneel.Lang.Get( "greetings.welcome" ) -- returns "Welcome :playername !"
    -- or in any language :
    Daneel.Lang.Get( "french.greetings.welcome" ) -- returns "Bienvenu :playername !"

    -- replace bits of text within the lines :
    Daneel.Lang.Get( "greetings.welcome", { playername = "John" } ) -- returns "Welcome John !"

Game object tags

They are used to group game objects together.

-- Set this game object has being an "enemy"
self.gameObject:AddTag( "enemies" )

-- Get all game objects that have one or several tag(s) :
local allEnemies = GameObject.GetWithTag( "enemies" )

Example projects

Daneel comes with two example projects that you can use to see some examples of how things works together.

Documentation

The documentation has now its own website (link below). I apologize in advance for typos and weird turn of phrase.

 

So that was the major new features for this version but there is a lot more of them (new and old). Check the documentation to learn about all of them !

Download v1.2.0

Go to the documentation

What’s next ?

Pretty much every thing can be improved in a way or another and I have already plenty of small improvement in mind throughout the code base. I am committed to make sure that every thing that already exists is as robust and bug-free as it can be. But that does prevent the addition of new features, one of which will be a particle emitter.

Aside from that, from now on, I will also make games because it’s really fun (especially with CraftStudio !) and it’s actually the best way to debug Daneel and find new useful features.

Bye ;)

How to easily create Fonts for CraftStudio

In its latest release, CraftStudio introduced the TextRenderer component and the Font asset (among many other things).

The Font asset is basically a grid of characters and may seems tedious to create because you have to manually place all the characters precisely on the fixed grid then set the width of each of them for rendering.

Hopefully some tools and a little bit of cleverness can help us out a lot. The overall process may involve quite a few steps but all are quite easy and fast to do.

I will explain two ways, both have the same goal which is to create a .png image that you simply copy and paste in CraftStudio’s Font editor.

First way : Inkscape

create_font_inkscapeIt’s the way Elisée used to create the two demo fonts Russo One and Titilium Web. He explains it in this post on the CraftStudio’s community forum.

Basically, he used Inkscape to create a grid of characters with the correct spacing. You can download the .svg file of the grid then edit it with any text editor (something like Window’s Bloc-notes or Notepad++, not Word) and search/replace the font name (Russo One for instance) by the name of the font you want to use.

Once this is done, open the file in Inkscape (if all you see is an empty box, this is because the characters are white, like the background). You may then edit the characters as you need them (adding shadows or other effects for instance). Changing the color is simple : just select all the characters then pick the color with the wizard at the bottom of the window.

create_font_inkscape_exportOnce you are happy with how the font looks, you need to export it as a .png. Just go to the File menu then Export Bitmap then click the Export button. Copy the .png you just created and paste it in the font editor in CraftStudio. If needed, adjust the characters (and texture) size to a width of 32 and a height of 48.

If your system does not possess the font you would like to use, just read the paragraph “Adding any font to your OS” below.

Inkscape is free and cross-platform.

Second way : generating the .png from a font file

windows_fontFirst download this tool : Windows Font to PHP Font. It only works on Window but if you are aware of such a tool for Mac or Linux, please let me know.

It lets you pick a font, style it (bold, italic,…) and set a height and width for the characters. Once you did that, click on the Save to file button to create a .gdf font file.

Now use this online font converter. Select the .gdf file you just created on your computer, then select the color of the font. Finally click on the Create image button. The image will appear at the bottom of the page, copy it then paste it in CraftStudio.

If the transparent background appear black in CraftStudio repeat the process but check the Magenta Background box. This solution won’t work if the characters have semi transparent parts because they will be tainted with magenta. In this case, leave the background transparent, copy the image in an image editing tool (instead of CraftStudio), then save the image as .png then copy and paste in CraftStudio.

Adding any font to your OS

Inkscape or the “Windows Font to PHP font” tool only uses the font that are installed on your operating system but installing a new font on your system is really straightforward : on Windows 7 (I don’t know how it works on Mac or Linux), you just need to download a .ttf font file, right-click on it then click Install. The font became usable by Inkscape or any other software that uses the system’s fonts.create_font_google_font

You may find thousands of fonts available to use for free online, and most of the repositories lets you download the .ttf file.

Here is an example with Google fonts : find your font, add it to your collection then click the arrow in the top-right corner of the page and click on Download the font families in your Collection as a .zip file.

Setting the character boxes

Once your texture and grid are setted up, you still need to set each characters boxes (the character width when they are displayed by the TextRenderer). There is no automated ways to do that but you can save yourself a lot of work by copying the an existing font.

Replacing the texture won’t change how the character boxes have been setted up for the previous font and if the two fonts are not too different, all you will have to do is adjust some of the boxes.

Minimalist Encounter – Ludum Dare 26

I participated to the 26th Ludum Dare challenge that happened this week-end (and still happens for the Jam competitors). As always the goal for the Compo competitors was to create a game alone in a maximum time frame of 48h, based on a theme revealed only at the last second.

I already did it once before, back in August 2012, and once again successfully shipped a game (well, kind of…) just on time. I also did another game in January, but with a team and for the Global Game Jam, another game creation event.

This time the theme was Minimalism, and I choose to reproduce Harvest: Massive Encounter, an already minimalist tower defense game that I enjoyed a lot. I wanted to built a resource management game for a while already, so this LD’s theme was the perfect occasion. Its certainly minimalistic on the inspiration side, but I really wanted to built this one and that was all the motivation I needed.

Continue reading

Introducing the Daneel framework for CraftStudio

Since the Global Game Jam in January where I worked with others on HeartZ, I spent quite some times to built Daneel, a project that’s only the foundation for many things I have in mind for CraftStudio

Daneel is a framework for CraftStudio that aims to sweeten and shorten the code you write, to extend and render more flexible to use the API, as well as to bring news functionalities.

Read the documentation

Here is a little overview of what it allows you to do :

Call getters and setters as if they were variable :

self.gameObject.name -- same as self.gameObject:GetName()

self.gameObject.name = "new name" -- same as self.gameObject:SetName("new name")

Access any component (including ScriptedBehaviors with a few configuration) on the gameObject in a similar way, like you can already do with the transform :

self.gameObject.modelRenderer

-- the "getters/setters as variable" thing also works on components :
self.gameObject.mapRenderer.map = "folder/map name" -- you can also see here that you can use the map name instead of the map asset

-- writing this same line "the old way" takes twice as much characters :
self.gameObject:GetComponent("MapRenderer"):SetMap(CraftStudio.FindAsset("folder/map name", "Map"))

Set variable or call setters in mass on gameObjects and components.

    gameObject:Set({
        parent = "my parent name",

        modelRenderer = {
            model = "model name"
        }

        myScript = {
            health = 100
        }
    })

Also :

  • Use the gameObject or asset name instead of the actual object with some functions
  • Simpler raycasting with `ray:InstersectsGameObject()` or `ray:Cast()`
  • Triggers (they perform a proximity check against some gameObjects and interact with them when they are in range)
  • Interact with gameObjects hovered by the mouse
  • Events
  • Hotkeys (fire events at the push of any button)

You can access the public project named “Daneel” (search for it in the Community Projects), with a small showcase scene and a few example scripts.

You may also discuss Daneel in its dedicated thread on the CraftStudio community forums.