You Are Here:

Community: Blogs

Widget Workshop's Forum Nokia Blog

Developing our first widget: Bombus

mobileradicals | 20 September, 2007 12:33

Firstly, sorry for the delay in writing up the next installment of our S2F blog - we found it difficult to develop and blog simultaneously. So, with that in mind, let's start with a confession:

The game's already finished! It's called Bombus, and as promised, it's a side-scrolling arcade game.

Bombus screenshots

Here's a video showing the gameplay:

Whilst developing the game we took notes, but to do each blog entry justice (by including a write-up after the end of each step) would have resulted in delaying the completion date significantly.

However, we now have some free time to write down our experiences, and more importantly, share some code. So whilst this might go against the S2F ethos slightly, we hope you can forgive us and hopefully seeing how the game turned out will help.

1. Getting started

Our first step was to download the SDK from the WidSets wiki. The wiki is an invaluable source of information containing general development guides as well as scripting and configuration documentation. The WidSets developer forum also proved useful as members of the WidSets team seem to visit often and are quick to offer help and advice.

The SDK consists of a set of command-line tools for compiling, invoking the emulator, uploading widgets etc (WidSets SDK wiki article). We used UltraEdit as our IDE, which is essentially a powerful text-editor. The SDK contains a syntax highlighting file for UltraEdit which helps with code readability. With the SDK installed, we encountered our first minor problem: widgets are distributed centrally from the WidSets server, so in order to login and subsequently upload/publish widgets, a connection to the server is necessary. Here at Lancaster University, we sit behind a proxy server, so we had to define our connection settings before we could connect.

So instead of:

> devkit login username password

We had to use:

> devkit --proxy wwwcache.lancs.ac.uk:8080 --auth user1 pass1 login user2 pass2

Where user1 and pass1 are our proxy authentication details and user2 and pass2 are our WidSets username and password (the proxy need only needs to be defined once). To register a developer account at WidSets, we visited http://dev.widsets.com/install - currently this link isn’t easy to find on the main site. N.B. The WidSets developer client is different to the regular client.

After following the guides on the wiki, checking out a few of the examples and with the scripting, configuration and stylesheet documentation open in the browser, we were ready to start.

We used the Hello World (found in examples/hello_world) example as the starting template for our own widget. Copying all the files from this directory to our working directory (bombus/) allowed us to bootstrap the development. The wiki provides a good overview of the files to are need to make up a widget here.

Here's what the first version of Bombus looked like...

Screenshots first step


Not much of a game yet, but we can get an idea of where our game content will be (on the blue canvas). The important files used to create this version are listed below.

Configuration file (widget.xml):
<?xml version="1.0" encoding="utf-8"?>
<widget spec_version="2.0">
<info>
<name>Bombus</name>
<version>0.1</version>
<author>Widget Workshop</author>
<shortdescription>
A one button side scrolling arcade game
</shortdescription>
<longdescription>
Guide Bombus through the cave.
</longdescription>
<tags>
bombus game arcade side scrolling one button
</tags>
</info>
<parameters>
<parameter
type="string"
name="widgetname"
description="Name of widget"
help="This is the name of the widget"
editable="false"
visible="true">
Bombus
</parameter>
</parameters>
<resources>
<code src="bombus.he"/>
<stylesheet src="style.css"/>
<img src="mobile_radicals.png" scale="false" />
</resources>
<layout minimizedheight="3em">
<view id="viewMini">
<label class="outerFrame">Bombus</label>
</view>
<view id="viewMain">
<script id="gameView" />
</view>
</layout>
</widget>
Helium script (bombus.he):
class {

// Command IDs
const int CMD_BACK = 1;
const int CMD_NEW_GAME = 10;
const int CMD_INSTRUCTIONS = 11;
const int CMD_ABOUT = 12;

// Member vars.
Shell gameShell;
Flow gameFlow;
Canvas gameCanvas;

// Menu items (mapped to softkeys)
MenuItem BACK = new MenuItem(CMD_BACK, "Back");
MenuItem OPTIONS = new MenuItem(OPEN_MENU, "Options");

// Create options menu (using chaining)
Menu MENU = new Menu()
.add(CMD_NEW_GAME, "New game")
.add(CMD_INSTRUCTIONS, "Instructions")
.add(CMD_ABOUT, "About");

// Push shell onto screen
void showShell(Shell shell) {
int w, int h = getScreenSize();
slideIn(-w, 0, w, h, shell);
}

// Pop shell off screen
void hideShell(Shell shell) {
int w, int h = getScreenSize();
slideOut(w, 0, w, h, shell);
}

// Called for each view element
Component createElement(
String viewId, String elementId, Style s, Object o) {

if(elementId.equals("gameView")) {

gameFlow = new Flow(getStyle("outerFrame"));
gameCanvas = new Canvas(getStyle("default"));
gameCanvas.setPreferredSize(-50, -50);
gameFlow.add(gameCanvas);

return gameFlow;

}
return null;
}

// Create minimized view
void startWidget() {
setMinimizedView(createView("viewMini", null));
}

void stopWidget() {} // Stop

// Create maximized view when the widget is opened
Shell openWidget() {
gameShell = new Shell(createView("viewMain", null));
showShell(gameShell); // Show main shell
return null; // We've already push shell into view
}

// Release resources
void closeWidget() {
gameCanvas = null;
gameFlow = null;
gameShell = null;
}

// Paint the gameCanvas
void paint(Component c, Graphics g, Style s, int w, int h) {
g.setColor(0x0000FF);
g.fillRect(0, 0, w, h);
g.setColor(0xFFFFFF);
g.drawString(
"Our canvas!", w / 2, h / 2, HCENTER | TOP);
}

// Get the menu
Menu getMenu(Shell shell, Component source) {
return MENU;
}

// Softkey event handler
MenuItem getSoftKey(Shell shell, Component focused, int key) {
if(key == SOFTKEY_OK)
return OPTIONS;
else if(key == SOFTKEY_BACK)
return BACK;
return null;
}


// Key event handler
boolean keyAction(Component source, int op, int code) {
return false; // Key event not consumed
}

// Action event handler
void actionPerformed(Shell shell, Component source, int action) {

switch(action) {
case CMD_NEW_GAME:
break;
case CMD_INSTRUCTIONS:
break;
case CMD_ABOUT: // Display 'about' info.
setBubble(
getImage("mobile_radicals.png"),
"Bombusnmobileradicals.com");
break;
case CMD_BACK:
// Pop shell
hideShell(shell);
break;
}
}
}
Stylesheet (style.css):
outerFrame {
align: hcenter vcenter;
background: solid #000000;
color: #FFFFFF;
width: 100%;
}
Please note, blogs after this will not post complete source listings, but instead provide important fragments that demonstrate key game concepts.
 
 

Rate This

 
 
Bookmark this page: DeliciousDiggFacebookGoogleYahooStumbleUponRedditDiigoTechnocratiTwitter  Share this page Share this page Print this Page Print this page Invite a friend Invite a friend
京ICP备05048969号    Email Newsletters Press Terms & Conditions Privacy Policy Sitemap Contact Us © 2009 Nokia