Monkey (programming language)
|
|
This article has multiple issues. Please help improve it or discuss these issues on the talk page.
|
| Paradigm(s) | multi-paradigm: structured, imperative, object-oriented, modular, reflective, generic, concurrent |
|---|---|
| Appeared in | March 1, 2011[citation needed] |
| Designed by | Mark Sibly |
| Developer | Blitz Research Ltd.[1] |
| Stable release | 0.70(f) (May 20, 2013) |
| Typing discipline | Static, Weak, Strong (Optional), Safe, Nominative, Partially Inferred |
| Influenced by | BlitzBasic, BlitzMax, C#, Java |
| Platform | Crossplatform |
| OS | Microsoft Windows, Mac OS X, Linux (IDE not available). (See the targets for a full list of platforms) |
Monkey is a high-level programming language designed for developing games for many different platforms, including desktop & laptop computers, mobile phones & tablets, and video game consoles. The language itself is an object-oriented dialect of BASIC, which the compiler translates into native source code for several target platforms, which is then compiled normally. Currently the official target platforms include: Windows, Mac OS X, Linux, Windows 8/Windows RT (Windows Store applications), Windows Phone 8, Xbox 360 (Based on C# & XNA), Windows Phone 7 (Also XNA based), Android, iOS, PSS/PSM (Deprecated/Suspended, C# & Mono based), HTML5 (Which is primarily based on JavaScript), and Flash. Monkey was created by Blitz Research Ltd, the makers of: BlitzBasic, Blitz3D, BlitzPlus, and BlitzMax.
Community-driven/user-made targets have also been created, some notable user-targets include: MonkeyMax (BlitzMax),[2]Monkey-Python (Python),[3] and a Nintendo DS target.[4]
History
Monkey was released on March 1st, 2011[citation needed], and it was designed by Mark Sibly of Blitz Research Ltd.[5] Monkey's principal implementation is as a source to source compiler that is able to convert Monkey source code to a number of other high-level languages (listed below).[6] The language is primarily focused on multi-platform game development. It supports object-oriented and generic programming, and has a strong type system similar to Java.
Since version 0.59, Monkey has integrated a built-in debugger for its C++ based targets.[7]
Mojo
Mojo is the official proprietary graphics 'module' for Monkey. Mojo has been written for all of Monkey's official game-based targets, this is done using the native programming languages of each target. Mojo is then wrapped using Monkey's "external-language" system. Mojo was designed primarily for writing simple 2D games in Monkey, but like many other APIs, it can also be used for other types of programs. Mojo also has primitive 3D capabilities,[8] but its recommended to use a native graphics library for that platform (There are also OpenGL wrappers that come with Monkey). Like Monkey itself, one of Mojo's goals is to make everything (Graphics and sound in this case) as consistent as possible on all of its supported platforms. Because of this, Monkey-based games tend to look almost identical on all platforms, despite sometimes being based on drastically different technologies.
Mojo currently doesn't render with WebGL for its HTML5/JavaScript versions, however, a member of Monkey's community known as Devolonter has done it himself.
Official targets (Garbage-collected)
- GLFW (OpenGL based C++ target for: Windows, Mac OS X, and Linux)
- Android (Java based)
- iOS (C/C++ based)
- HTML5 (JavaScript & HTML5 based)
- Adobe Flash
- XNA (XNA based C# target for: Windows, Xbox 360, and Windows Phone 7)
- Windows 8 / Windows RT (DirectX based C++ target usually used for Windows Store applications and games)
- Windows Phone 8 (Effectively the same as the Windows 8 target, but with support for Windows Phone 8)
- Deprecated/suspended targets:
- PSS/PSM [9] (C# / Mono based target, which is primarily for the PlayStation Vita)
Official targets (Not Garbage-collected)
- 'Standard' C++[10] (Used for console applications and tools. Monkey's translator was built using this.)
Unofficial/community-driventTargets
You can find most of Monkey's unofficial/community driven targets here: The community's "User Targets" section.
Notable games made using Monkey
- New Star Soccer Mobile - Won Sports/Fitness 2013 BAFTA[11]
- More games/other made in Monkey can be found here: The community's "Apps" section.
Sample code
' This example relies on the 'Mojo' module, so it will not compile with the STDC++ target. ' Mojo comes with all full versions of Monkey, and it works on all official game-targets. ' Classes and functions such as Image, and App, LoadImage, and DrawImage are located in Mojo. ' Enable strict mode. Strict ' Import the mojo module. Import mojo ' The entry point for monkey: Function Main:Int() New GameApp Return 0 End ' The main class which expends Mojo's 'App' class: Class GameApp Extends App Field player:Player ' Override Mojo's 'OnCreate' method: Method OnCreate:Int() ' OnCreate is called automatically when the 'App' class is created. ' Most media should be stored in a folder called "ProjectNameHere.data". ' Load the image player.png, then return the 'Image' class to 'img'. ' Mojo assumes that what you're loading is in the "ProjectNameHere.data" folder. Local img:Image = LoadImage("player.png") ' Create a new instance of our player class using the image we loaded. player = New Player(img, 100, 100) ' Self.player could also be used here. ' Set the update-rate to 60 frames per second. SetUpdateRate(60) ' Returning zero usually signifies that there were no errors in a method like this. Return 0 End ' Override Mojo's OnUpdate method: Method OnUpdate:Int() ' OnUpdate is called automatically several times per second. ' The number of times this is called is based on the update-rate. ' Add '1.0' to the player object's 'x' variable(Float). player.x += 1.0 ' If the value of 'x' exceeds 100, set it to zero: ' This could also be done using 'Mod', the modulus operator. If (player.x > 100) Then player.x = 0 Endif ' End could be used here instead of Endif ' Everything went according to plan, now return zero. Return 0 End ' Override Mojo's OnRender method: Method OnRender:Int() ' OnRender is usually called as many times as OnUpdate. ' Normally, all graphical/drawing operations must be done in here. ' However, you can manually render by using BeginRender() and EndRender(). ' Clear the screen, then display a color based on the values specified(RGB). Cls(32, 64, 128) ' Call our player object's 'Draw' command. player.Draw() ' Everthing went according to plan, now return zero. Return 0 End End ' The player class that was referenced above: Class Player ' Define all of our fields (Variables): Field x:Float, y:Float Field image:Image ' Overloading 'New' works the same way as a constructor in other languages. Method New(img:Image, x:Float=100, y:Float=100) ' Due to the arguments, 'Self' is required in this situation: Self.image = img Self.x = x Self.y = y End ' 'Draw' is a simple command that draws our image using the coordinated specified. Method Draw:Void() DrawImage(image, x, y) End End
Interfacing with External languages
Monkey provides a relatively simple way to let you work with the language it's going to convert to, it does this using an external-code directive, which it calls "Extern". Like how Monkey handles Public and Private directives, any code written after an external-code directive is considered external, and will not be treated the same as normal Monkey code. When Monkey converts itself into the desired language, it uses all of the "prototypes" specified after an "Extern" directive as macros for the native code you wrote.
Here's an example of how Monkey's external code would be setup:
#If CONFIG = "debug" #DEBUG_ENABLED = True #Else #DEBUG_ENABLED = False #End ' You may want to put this in a sub-folder (Mojo and other modules use "native" for native source code). Import "InsertNameHere.cpp" ' You can optionally add 'Private' to an external directive. Example: "Extern Private" Extern ' All code after this point is used as prototypes for C++ code. ' This bit tells Monkey that the native class called "native_Test", will be called Test when used in Monkey. ' This same thing can be done with other things such as functions, methods, fields, etc. Class Test="native_Test" ' Global variables: Global GlobalVariable:Int="globalVariable" ' Fields: Field FieldVariable:String="fieldVariable" End Public ' Everything after this point is public Monkey code. Function Main:Int() Local T:Test = New Test() Return 0 End
If you're only interested in seeing the final code example itself, please scroll down. Here's some needed information about using C++ and Monkey together (Mainly for GLFW users):
// If you're using a higher-level language like C# or Java, it tends to be a lot more stream-lined with Monkey.
// C++ Specific Notes (Does not apply to most of the external languages):
// This native-code was written with the GLFW target in mind,
// it may or may not work with the iOS and Windows 8/Windows Phone 8 targets,
// and definitely will not work with the "Standard C++" target.
// However, that's not to say that the external directive doesn't work on these platforms.
/*
For the record, when using external C++ code with Monkey, unless you specifically set it up,
your code is generally not going to be garbage collected.
So for the most part, you will need to handle some things yourself.
*/
/*
If you're using external C++ code in your game/other, and you're only using small things like functions,
these next two sections don't really apply to you. Scroll down for the C++ example.
*/
/* Automatic memory management with Monkey and GLFW(C++):
For the most part, all you need to do is setup your classes with a bit of code for garbage collection.
Here's an example of an automatically managed/garbage-collected class:
*/
class myClass : public Object
{
public:
// When you're done with an object made from this class, please make sure to clean up anything in this class that isn't garbage collected.
// Members are not specifically garbage collected just because objects made using this class are.
myClass() { } // Insert your code here (Initialize things as you normally would)
myClass* m_new()
{
// Look below for an explanation about the preprocessor.
// These parts with the preprocessor are 100% optional.
#if defined(CFG_DEBUG_ENABLED) && CFG_DEBUG_ENABLED == 1
DBG_ENTER("Native: myClass")
// This only works with Visual C++ (On Windows), so you may want to remove it
DBG_LOCAL((myClass*)this, "Self")
DBG_INFO("Unable to find location."); // If you want to add the current file's name, you can.
#endif
return this;
}
void mark() { Object::mark(); return; }
#if defined(CFG_DEBUG_ENABLED) && CFG_DEBUG_ENABLED == 1
String debug()
{
String t = "(myClass)\n"; // This is what's displayed on the side of the IDE.
// If you want to add variables so the debugger can see them, use this.
// t += dbg_decl("Display name of variable", &ActualVariable);
return t;
}
#endif
// Add anything else you want to this class. (ints, floats, structs, pointers, etc)
};
// The following debug-related code should be optional, but still very useful for debugging:
#if defined(CFG_DEBUG_ENABLED) && CFG_DEBUG_ENABLED == 1
String dbg_type(myClass**m) { return "myClass"; }
// If you want to do this, you will need to setup the preprocessors yourself.
// Simply add something like this to your Monkey code:
/*
#If CONFIG = "debug"
#DEBUG_ENABLED = True
#Else
#DEBUG_ENABLED = False
#End
*/
#endif
// When creating this class, you'll need to do something like this:
void FunctionNameHere()
{
myClass* m = ((new myClass)->m_new());
// [Insert code using the object as you normally would here] (With pointers)...
// Then when you're done, make sure to remove any references to it, and it should get collected.
m = NULL; // Or nullptr, either should work.
return;
}
/* Manual memory management with Monkey and GLFW(C++):
When using C++ external code (with GLFW), there's a number of ways to free things from ram manually.
One way is to make a class that contains your class, and go from there.
Another way is to delete things 100% manually,
the biggest downside to this is that Monkey still thinks it exists, so you will need to set your variable to null.
A work around for that would be using a Monkey-based class to hold the native (C++) class,
and simply having both objects keep track of each other, which is similar to the other method, and is what I'm doing here.
If you're interested in this, try adding this after an "Extern" directive: Function Delete:Void(O:Object)="delete"
Edit that bit of code if you need to, you could always just make overloads, and use your external class itself as the argument.
Two of the bigger issues with manual memory management are that your class needs to extend the public 'Object' class in debug-mode,
and debugging code like that tends to break very easily.
*/
// After all of that, the end result is this:
class native_Test : public Object
{
public:
// Constructor(s):
native_Test()
{
Print("Hello, I'm an external object.");
}
//~native_Test(); <- The destructor isn't needed for this specific class.
native_Test* m_new()
{
#if defined(CFG_DEBUG_ENABLED) && CFG_DEBUG_ENABLED == 1
DBG_ENTER("Native: Native_Test")
//DBG_LOCAL((native_Test*)this, "Self")
DBG_INFO("(C++ NATIVE)");
#endif
return this;
}
void mark() { Object::mark(); return; }
#if defined(CFG_DEBUG_ENABLED) && CFG_DEBUG_ENABLED == 1
String debug()
{
String t = "(Native: Test)\n";
t += dbg_decl("FieldVariable", &fieldVariable);
return t;
}
#endif
// Global/Static variables:
static const int globalVariable = 1024;
// "Fields":
String fieldVariable;
};
#if defined(CFG_DEBUG_ENABLED) && CFG_DEBUG_ENABLED == 1
String dbg_type(native_Test**t) { return "Native: Test"; }
#endif
Final notes:
- Less modular languages (C++, JavaScript, etc) tend to just throw all of the code into one file.
- C++ based targets cannot include header files (From within Monkey), you'd need to change their file extension to "cpp".
- C++ based targets can in-fact use namespaces when using an alias for native code. Here's an example: Function MyFunction:Void()="myNamespace::myFunction"
See also
- HaXe - a programming language that compiles to JavaScript, C++, Java, C#, and several other languages
References
- ^ Monkey's official website
- ^ MonkeyMax Source Code Repository from Google Code
- ^ User Made Python Target Source Code Repository from Google Code
- ^ User Made Nintendo DS Target For Monkey
- ^ http://www.blitzbasic.com/faq/faq_entry.php?id=29 Blitz Research Ltd
- ^ Official Monkey About Page from Blitz Research LTD
- ^ Monkey Version 0.59 Release Notes from Blitz Research LTD
- ^ Update-log on MonkeyCoder
- ^ A forum post made by Mark Sibly (Monkey's creator) from www.monkeycoder.co.nz
- ^ A forum post made by Mark Sibly (Monkey's creator) from www.monkeycoder.co.nz
- ^ Official BAFTA Sports/Fitness 2013 Category Page from bafta.org
External links
- Official website Blitz Research, Monkey author, distributor
- German forum: http://www.monkeycoder.de
- Russian Monkey community
- Jungle IDE, an advanced IDE for the Monkey programming language: http://www.jungleide.com
|
|||||||||||||||||
