Smart Mobile Studio
  • News
  • Forums
  • Download
  • Store
  • Showcases
    • Featured demos
    • The Smart Contest 2013, Round 1 – Graphics
  • Documentation
    • Get the book
    • System requirements
    • Prerequisites
    • Getting started
      • Introduction
      • Application architecture
      • The application object
      • Forms and navigation
      • Message dialogs
      • Themes and styles
    • Project types
      • Visual project
      • Game project
      • Console project
    • Layout manager
    • Networking
      • TW3HttpRequest
      • TW3JSONP
      • Loading files
  • About

Author Archives: Jon Lennart

Only days left

Posted on 11.05.2012 by Jon Lennart Posted in News 17 Comments
Only days to go

Only days to go

It is now only a matter of days before Smart Mobile Studio 1.0 goes on sale. It marks the end of a one year journey for us to create something completely new for the object pascal community, written in nothing but Delphi itself. But while the journey from idea to realization is over, the next stage of Smart technology is about to begin – and it’s going to be big. Really big.

In this our first release, focus has been on providing you with a solid foundation. A visual javascript component library (VJL) with identical parent/child relationship to what you are already familiar with. An integrated development environment with essential functionality including a component palette. And last but not least, a mock form designer with live rendering of the actual HTML5.

As we move ahead each aspect of the formula will be expanded, strengthened and refined. And while we cant blow the whistle just yet, we have something very exciting in our labs that is going to change everything. Forever.

This is quite possibly the most significant Pascal
development to be watching right now, and brings
the wonderful Pascal language to the world of
Internet development! -Simon Stuart, Delphi developer via Google+

FireFox HTML5 javascript Mozilla OP4JS Safari Safari Mobile Smart Mobile Studio webkit

Support for helper objects

Posted on 03.05.2012 by Jon Lennart Posted in Developers log

Smart Mobile Studio now supports helper objects for various elements, including classes, records and arrays. Helper’s are extremely valuable in leveraging complex data-structures. This is a very powerful addition to Smart’s already impressive list of “must have” features when working with javascript. Features that no existing javascript framework or utility provides.

Here is a small taste of how you can use a helper object to enrich something as simple as an array of TPoints. These are pure “trig” rotations (just one way of doing it).

[sourcecode language=”delphi”]
unit w3polygons;

interface

uses w3system;

type

TPolygonHelper = helper for TPointArray
Procedure Rotate(const angle:Float;const centerX,centerY:Float);
Procedure Scale(factor:float;Const centerX,centerY:Float);
End;

Implementation

procedure TPolygonHelper.Rotate(const angle:Float;
const centerX,centerY:Float);
var
i: integer;
r,p: Float;
begin
if self.Length>0 then
Begin
for i:=self.low to self.high do
begin
r:=sqrt(sqr(self[i].X – centerX) + sqr(self[i].Y – centerY));
p := angle + arcTan2(self[i].Y – centerY, self[i].X – centerX);
self[i].x:=Round(centerX + r * cos(p));
self[i].y:=Round(centerY + r * sin(p));
end;
end;
end;

Procedure TPolygonHelper.Scale(factor:Float;
Const centerX,centerY:Float);
var
i: integer;
r,p: float;
begin
if self.length>0 then
begin
for i := self.low to self.high do
begin
r:= factor * sqrt(sqr(self[i].X – centerX) + sqr(self[i].Y – centerY));
p:= arcTan2(self[i].Y – centerY, self[i].X – centerX);
self[i].X := Round(centerX + r * cos(p));
self[i].Y := Round(centerY + r * sin(p));
end;
end;
end;

end.

[/sourcecode]

Archimedes spiral

Posted on 30.04.2012 by Jon Lennart Posted in Developers log

Here is a fun graphical effect. Start a new game project and paste in the following code (remember to keep the unit name). The effect is known as Archimedes spiral, although we play with the numbers to create a strobe like effect.

The numbers of life

The numbers of life

[sourcecode language=”delphi”]
unit ArchSpiral;

interface

uses w3system, w3components, w3ctrls, w3application,
w3game, w3gameapp, w3graphics, w3components;

type
TApplication = class(TW3CustomGameApplication)
private
{ Private methods }
FaValue: Float;
FbValue: Float;
protected
{ protected methods }
procedure ApplicationStarting; override;
procedure ApplicationClosing; override;
procedure PaintView(Canvas: TW3Canvas); override;
end;

implementation

procedure TApplication.ApplicationStarting;
begin
inherited;

FaValue := 5.0;
FbValue := 1.0;

//Initialize refresh interval, set this to 1 for optimal speed
GameView.Delay:=20;

//Start the redraw-cycle with framecounter active
//Note: the framecounter impacts rendering speed. Disable
//the framerate for maximum speed (false)
GameView.StartSession(true);
end;

procedure TApplication.ApplicationClosing;
begin
GameView.EndSession;
inherited;
end;

// Note: In a real live game you would try to cache as much
// info as you can. Typical tricks are:
// 1: Only get the width/height when resized
// 2: Pre-calculate strings, especially RGB/RGBA values
// 3: Only redraw what has changed, avoid a full repaint
// The code below is just to get you started

procedure TApplication.PaintView(Canvas:TW3Canvas);
var
cx,cy: Float;
i: Integer;
angle: Float;
x,y: Float;
begin
fbValue := fbValue + 0.0009;

// Clear background
Canvas.FillStyle := ‘rgba(0,0,99,0.3)’;
Canvas.FillRectF(0, 0, GameView.Width, GameView.Height);

// Draw our framerate on the screen
Canvas.Font := ’10pt verdana’;
Canvas.FillStyle := ‘rgb(255,255,255)’;
Canvas.FillTextF(‘FPS:’ + IntToStr(GameView.FrameRate),10,20,MAX_INT);

cx := GameView.Width div 2;
cy := GameView.Height div 2;
Canvas.MoveToF(cx,cy);
Canvas.BeginPath;
for i := 0 to 719 do
begin
angle := fbValue * i;
x := cx + (FaValue + FbValue * angle) * cos(angle);
y := cy + (FaValue + FbValue * angle) * sin(angle);
Canvas.LinetoF(x,y);
end;
Canvas.StrokeStyle := ColorToWebStr(clWhite);
Canvas.Stroke;
end;

end.
[/sourcecode]

Demo and code

You can download the project source code here: ArchSpiral.zip

You can find an online demo here: ArchSpiral demo

(Or simply scan the QR code below with your phone)

qrcode

Smart game: WarTrail

Posted on 28.04.2012 by Jon Lennart Posted in News

Eric Grange has added his entry into the PGD competition, a very nice game called Wartrail. The game is coded using Smart Mobile Studio and runs fine under iOS (iPhone and iPad), chrome and FireFox.

Wartrail main screen

Wartrail main screen

The object of the game is to defend your bases against incomming enemies by placing turrets at strategic positions. Each turret costs money and part of the challenge is to figure out where each turret will have the most impact.

Wartrail level 01

Wartrail level 01

Realtime control rendering

Posted on 25.04.2012 by Jon Lennart Posted in Developers log, News

First taste of things to come: real time rendering of design controls. Since there is a delay between the actual rendering of the html graphics and the design movements, we will probably have a preview button that triggers the process. But all in all it is very nice to see our theories work out πŸ™‚

Smart now renders the design controls via webkit

Smart now renders the design controls via webkit

What is new in community beta 2?

Posted on 25.04.2012 by Jon Lennart Posted in News 4 Comments

Below are some of the new features that has been added to Smart Mobile Studio community beta II. We hope you find our efforts in creating this product,a product that is both unique, innovative and extremely powerful, useful and interesting. Our customers can look forward to gestures, databases, even better browser support, Phone-Gap support and (last but not least) WebGL. We also aim for tight integration with classical Delphi server technology, like the Remobjects remoting framework and the C# websocket hub.
Continue reading→

C# fpc Free Pascal HTML5 javascript JS mono Object Pascal OP4JS Remobjects Smart Mobile Studio WebSocket

Firefox, direct JS access and cleanup

Posted on 20.04.2012 by Jon Lennart Posted in Developers log
VJL Lion

I have no reason for this picture

I finally took the plunge and decided to really give the RTL a makeover. I was supposed to wait until Smart v1.1 with this, but releasing a product only to alter the RTL radically later would be unfair to our customers. Better to put in place a foundation that wont break the codebase later and that we can build on. So for the past 5 days I have edited every single method and class in the RTL’s foundation. But for what you say? Why fix what already works?

One of the hidden gems that my buddy Eric added to the compiler, is that we have direct access to the real javascript objects. You might have noticed that we used to keep a reference to the actual HTML Tag by use of TObject? In the older (and current) API all visual components have a property called tagRef. The problem was – this reference was both slow and dangerous. If you try to call any of it’s methods the app will crash, because it points to the real javascript handle and not our virtual method table.

Using a TObject reference also meant a greater speed penalty, since you had to typecast and test in a variety of ways before you used it. But now, all that is a thing of the past. The tagRef property has been completely removed from the RTL and has been replaced by a proper THandle. What is the fuzz about? Well, this property IS the actual javascript object. So, Eric in his infinite wizdom added support for magic stuff like:

[sourcecode language=”delphi”]
Self.Handle.style[‘backgroundColor’]:=clRed;
[/sourcecode]

What happens here is that you are accessing the javascript object directly, with nothing in between (!). As you can imagine, this gives us a tremendous advantage in speed over other solutions. It also means that the compiled code will be smaller, more efficient – and most importantly, easy to maintain. So now you can interact directly with the native DOM elements without an ASM section.

Speed injection

An example of just how much extra juice we managed to squeeze out of the browser with this rewrite, can be demonstrated by the “plasma” graphics demo we posted earlier (donated by a tester). Under the older RTL it rendered 120.000 pixels (manually plotted into the HTML5 graphics context via R,G,B,A) at roughly 4 frames per second on an iPhone 4S. That is extremely slow (but considering the amount of calls involved, im surprised we got 4 frames at all). After I ejected the use of tagRef and re-wrote parts of the w3graphics.pas unit, I now get 11 frames per second. Please remember that this extremely fast for a scripting engine, being able to draw 120.000 * 4 bytes eleven times a second. On my iMac it runs at a decent 80 FPS, which is even more impressive.

And this is just for starters. To keep the RTL backwards compatible I have retained the functions in w3system.pas (things like w3_setStyle, w3_setAttrib and so on), which means there are actually thousands of calls being made that are now redundant. It will take a lot of energy to get rid of them by Monday – but when I decide on something I never quit until it’s done.

Structure helpers

Following up on Delphi’s introduction of record functions, I have stripped the older functions for making and working with TRect, TRectF, TPoint and TPointF – and instead placed them directly in the record itself. This is much more uniform and leaves little doubt where a function should be (so new users dont have to wonder what unit function X resides in). Here is the interface for TRect as of writing. More and more functions will be added, but this is the “bare bones” i guess:

[sourcecode language=”delphi”]
TRect = Record
Left:Integer;
Top:Integer;
Right:Integer;
Bottom:Integer;
function Width:Integer;
function Height:Integer;
function toString:String;
function topLeft:TPoint;
function BottomRight:TPoint;
function Clip(Const RectToClip:TRect):TRect;
function Empty:Boolean;
function NullRect:TRect;
function Compare(Const aRect:TRect):Boolean;
function ContainsRow(Const aRow:Integer):Boolean;
function ContainsCol(Const aCol:Integer):Boolean;
function ContainsRect(Const aRect:TRect):Boolean;
function ContainsPos(Const aLeft,aTop:Integer):Boolean;
function ContainsPoint(Const apoint:TPoint):Boolean;
function Intersect(Const aRect:TRect;var intersection:TRect):Boolean;
function Expose(const aChildRect:TRect):TExposure;
function Make(Const aLeft,aTop,aWidth,aHeight:Integer):TRect;overload;
function Make(Const aWidth,aHeight:Integer):TRect;overload;
function MakeAbs(Const aLeft,aTop,aRight,aBottom:Integer):TRect;
End;
[/sourcecode]

FireFox support

The first version of Smart Mobile is designed exclusively for webkit, which means Safari mobile (iPad, iPod, iPhone), Android and equivalent desktop browsers. So little or no effort has gone into making Smart apps run on Opera or FireFox. But with some tweaks I now have a Sprite3d App running under FireFox as well πŸ™‚

The bootstrap code (the section of code that initializes and starts your application) has been altered to include a browser check. So now it checks what system you are running and cache’s known style-prefixes and other information. The magic function that will make all the difference is called “w3_CSSPrefix”. This will help make your CSS calls “universal”. So where you would previously have written:

[sourcecode language=”delphi”]
w3_setStyle(handle,’webkitTranslate’,F3dState);
[/sourcecode]

You can now make it run on all browsers by changing it to:

[sourcecode language=”delphi”]
w3_setStyle(handle,w3_CSSPrefix(‘Translate’),F3dState);
[/sourcecode]

Hardware accelerated animations and events are a bit crappy on FireFox at the moment (in terms of commonalities), for instance their “animation end” event don’t fire as it’s supposed to, and it also deviates from the naming convention used elsewhere. So mozAnimationEnd wont do. I’ll have to come up with a solution for that. But full FireFox support wont happen until later. But you can prepare your app for universal support by using the w3_cssPrefix function.

API drivers

The only way to fully maximize the potential of all platforms is to create a common ground, but one that is rich enough to cater for a browser’s unique features. As such, I have decided to create a driver system to solve the browser compatibility problems once and for all. This is currently being prototyped but should make it into Smart v1.5 probably. In short youΒ  have a basic class with functions for getting the correct style names (and more) for the current browser. The driver will also contain functions to examine device capabilities (is camera supported, is database supported, is orientation supported, touch, sound formats, image formats — the whole multimedia spectrum). When your app starts, the browser will be recognized – and the appropriate driver created. The RTL will then reference the driver to get the correct properties to set.

As a bonus, anyone can write a new driver should a different browser appear on the marked. And should there be changes, you simply update the driver rather than every n’th class or method in the RTL.

The javascript punters are going to go “whaaat? how did they do that?”. Easy, object pascal πŸ™‚

Realtime plasma effect

Posted on 04.04.2012 by Jon Lennart Posted in Developers log

Now this is something you dont see every day under javascript, an old-school demo effect called “plasma” πŸ™‚ It’s a rare thing in a browser due to the fact that each pixel has to be set for every redraw (400 x 400 = 160 000 pixels). So naturally it’s hard to make it move under javascript. But it works pretty good (this is of-course written in Smart). I remember 25 frames on the Amiga was concidered OK, so this is pretty cool stuff πŸ™‚

This demo was donated by Jason Reid. Thumbs up Jason!

400 x 400 32bit running at 50+ frames per second

400 x 400 32bit running at 50+ frames per second

demo effect plasma

Tetris arrives in Sparta

Posted on 03.04.2012 by Jon Lennart Posted in Developers log
A very nice tetris clone!

A very nice Tetris clone!

One of the beta-testers really put the system to it’s test. He received the beta – and the next day he submitted a fully blown Tetris clone to us. It is once again a nice testament to just how easy it is to port over Delphi code and make it spin under HTML5 with Smart.

So hat off to Christian! Talk about getting into the RTL quickly. I wasted my entire lunchtime playing this πŸ™‚ Way to go, cheers!

Game coding under Smart

There are currently 2 ways of creating games under Smart. The first is naturally by creating a game project (clicking “new project” -> Game) which will establish a bare-bones HTML5 canvas application. This means no form designs and is more suitable for low-level coders and people who want to squeeze the last drop of juice out of the browser.

The second way, is to create a normal visual application and then add the unit “w3sprite3d” to the uses list. This gives you access to a class called TW3Sprite. TW3Sprite implements a javascript API called sprite3d (no dependencies, we re-created it in smart), which simply put allows you to easily rotate, scale and move the control around the screen – and it’s all done using hardware acceleration (see older posts about Sprite3d and also check out the docs for the library if you are unsure about it).

I also took the liberty to speed up Sprite3d a bit, using and/or operators rather than ad-hoc string replacements. So you should get better speed under Smart.

Depending on your game type, either solution will serve you well – and you will have a serious advantage over classical JS programmers which must write tons of code to get the same level of control and infrastructure.

For a look at what Sprite3d can do, have a look at this article:Β  Retro demo coded in Smart

Demo and code

You can download the project source code here:Β  Tetris.zip

You can find an online demo here:Β  Tetris demo

(Or simply scan the QR code below with your phone)

qrcode

code demo game tetris

Keyboard events, how to?

Posted on 03.04.2012 by Jon Lennart Posted in Developers log, Documentation

Smart supports normal keyboard events for all HTML elements that triggers them. It can be confusing since we bolted the events into TW3CustomControl – which gives the impression that you can catch events from everything. Sadly this is not the case (support varies between browsers – and there is the technicality of “setfocus” which is not consistent under browsers. A native call to alert for instance, breaks the focus cycle that we take for granted in native applications).

I wanted to share how you can hook into the global keyboard event chain of the window object. This is of-course a must for games and multimedia designed for the desktop rather than touch devices. You also want to catch and buffer the key-presses to make your games respond as quickly as possible.

In this example we are going to setup the event handler inside a form. If you use multiple forms in your app but want to isolate keyboard handling handling on a global scale, then you should move this code to your application class rather than the form. Either way, here is how you can do it:

[sourcecode language=”delphi”]

// We start off by binding our handler to the event.
// In this case we bind to the window handle.
Procedure TForm1.InitializeObject;
Begin
inherited;
{$I ‘Form1:impl’}
w3_Bind2(browserapi.getwindow,’onkeydown’,doKeyDown);
End;

// Here we catch the JS event, extract the event value we want
// And ship it off to our handler. In a game, I would handle the
// key here since the extra call adds overhead. Every CPU cycle
// counts in the world of HTML5 programming.
Procedure TForm1.doKeyDown;
var
mCode: Integer;
begin
asm
@mCode = event.keyCode;
end;
HandleKeyDown(self,mCode);

(* As an alternative, you can also access JS objects via a variant,
which is a neat way of getting access to the native JS object
directly:

var
mEvent: variant;
Begin
asm @mEvent = event; end;
case mEvent.keyCode of
//do your thing here
end;
end;
*)
end;

// This is basically the standard onKeyDown event handler that
// all Smart components have. But by rule only input elements
// actually bouble this event. So for games and fullscreen apps
// it makes sense to centralize handling in one place.
procedure TForm1.HandleKeyDown(Sender:TObject;aKeyCode:Integer);
begin
writeln(aKeyCode);
end;
[/sourcecode]

If you want the other events, like onKeyPress – simply look at how TW3CustomControl does it (w3components.pas unit). All event handling methods are prefixed with CB (callback). Just copy the code into your form or app unit and adapt it. The keyboard events will be added to TW3CustomApplication in the next release.

event how-to keyboard

Fixes and progress

Posted on 03.04.2012 by Jon Lennart Posted in Developers log 2 Comments

Wow – I would never have thought so many people would download the beta! Or should I say alpha. It really was a disaster to find out that the auto-complete on monkeynews replaced our new 0.5.x build zip-name with the older alpha zip-name. So almost 100 people downloaded the wrong zip. Thankfully we corrected it, so the wast majority of users got the right version.

So please double-check: If the title of the IDE does not say “build 0.5.x” then you must go to your email (we issued a correction message) and download the beta version! I have been cursing since friday because of that mistake.

Make sure your copy have this title

Make sure your copy have this title

Although this blunder put a shadow over the whole release experience, the weekend ended as a small victory due to all the positive feedback we got (obviously from people who got the right download link). My personal favorite was “It bloody works! Awsome!”. That comment made my day πŸ™‚

Ok let’s wrap it up

I am happy to say that a huge chunk of the proposals and bugs have been fixed. I have also started on smarting up the IDE a bit, so right now I’m adding the final touches to “CTRL + CLICK” functionality like we have in Delphi. It already recognizes unit-names, class-names and method-names from the entire RTL – so it looks good. Not sure how to get synEdit to play ball though, but i’ll find a way.

So all in all we have the following chores left:

  • Finish the designer with common editing functions
  • Finish the globals editor
  • Get rid of the buggy synEdit search/replace dialogs (!)
  • Write property editors for font, border etc. so they show up in the inspector

As far as the RTL goes I have a couple of items on my list:

  • Global key hook for full screen apps
  • Add code donated by friends to the RTL (gestures, sound-api etc.)
  • Speed fixes, better error management and more compile options (css as external file etc.)

And that’s basically it for version 1.0 in terms of features. So it’s time to tie up the last lose ends, double, triple and quad check everything – and then it’s done.

The future

  • Databases and datalists
  • Support all browsers
  • webGL

Paying customers will receive updates sequentially (which includes IDE enhancements, new units, updates to the RTL, platform files and compiler updates) of-course. I already have around 200 items on my “must add” list for version 1.1 (including support for remobjects services) so don’t think we will be resting on our laurels πŸ™‚

Datalists is really going to surprise you. It’s actually very close to the old TDataset terminology (I will probably call it TDataset to make it more familiar).

Jai Jai Ganesha!

2d tile drawing for game programmers

Posted on 01.04.2012 by Jon Lennart Posted in Developers log, Documentation 2 Comments

The following is a class that allows you to draw game tile graphics easily. A game tile is basically just a small chunk of graphics (typically 16×16 or 32×32 pixels in size) that you use to display game maps. Typical examples are the older Super Mario games from Nintendo, or the Sega megadrive Sonic games.

Here is an example of a tile-set which you can use (the tileset below is public domain)

A classical 16x16 tileset

A classical 16x16 tileset

And here is the class you can use to draw the tiles

[sourcecode language=”delphi”]
unit SpriteSheet;

interface

uses w3ctrls, w3graphics, w3System;

type

TW3SpriteSheet = Class(TObject)
private
FImage: TW3Image;
FReady: Boolean;
FColumns: Integer;
FRows: Integer;
FTotal: Integer;
FWidth: Integer;
FHeight: Integer;

procedure HandleImageReady(sender:TObject);
Procedure setWidth(aValue:Integer);
procedure setheight(aValue:Integer);
Procedure ReCalcInfo;

public
Constructor Create;virtual;
destructor Destroy;Override;

Procedure LoadImage(aUrl:String);
Procedure Draw(Canvas:TW3Canvas;dx,dy:Integer;FrameIndex:Integer);

Property SpriteWidth:Integer read FWidth write setWidth;
Property SpriteHeight:Integer read FHeight write setHeight;
Property Ready:Boolean read FReady;
End;

implementation

Constructor TW3SpriteSheet.Create;
Begin
inherited Create;
FImage:=TW3Image.Create(NIL);
FImage.OnLoad:=HandleImageReady;
FWidth:=32;
FHeight:=32;
end;

destructor TW3SpriteSheet.Destroy;
Begin
FImage.onLoad:=NIL;
FImage.free;
inherited;
end;

Procedure TW3SpriteSheet.setWidth(aValue:Integer);
Begin
FWidth:=Max(aValue,4);
ReCalcInfo;
end;

procedure TW3SpriteSheet.setheight(aValue:Integer);
Begin
FHeight:=Max(aValue,4);
ReCalcInfo;
end;

Procedure TW3SpriteSheet.ReCalcInfo;
var
img : Variant;
Begin
if FReady then Begin
img:=ObjToVariant(FImage.TagRef);
FColumns:=(img.width+1) div FWidth;
FRows:=(img.height+1) div FHeight;
FTotal:=FColumns * FRows;
end else Begin
FColumns:=0;
FRows:=0;
FTotal:=0;
end;
end;

procedure TW3SpriteSheet.HandleImageReady(sender:TObject);
Begin
FReady:=True;
ReCalcInfo;
end;

Procedure TW3SpriteSheet.LoadImage(aUrl:String);
Begin
FReady:=False;
ReCalcInfo;
FImage.LoadFromUrl(aUrl);
end;

Procedure TW3SpriteSheet.Draw(Canvas:TW3Canvas;
dx,dy:Integer;FrameIndex:Integer);
var
sx,sy: Integer;
Begin
if FReady then
Begin
sx:=FrameIndex mod FColumns;
sy:=FrameIndex div FRows;
Canvas.DrawImageF(ObjToVariant(FImage.TagRef),
sx*SpriteWidth, sy*SpriteHeight,
SpriteWidth, SpriteHeight,
dx, dy, SpriteWidth, SpriteHeight);
end;
end;

[/sourcecode]

In our next installment I’ll give you some examples of how to use it

Pascal game developer’s compo!

Posted on 31.03.2012 by Jon Lennart Posted in Developers log
Waste of time? Think again!

Waste of time? Think again!

Many programmers don’t get the demo scene. What could be the point of spending hours, days and weeks on creating effects? Well for me the demo scene has been one of the best things in my life. I grew up with Commodore 64, MSX, Atari and Amiga machines. And while we all loved to play games only the few asked the magical question “how”. Some were happy to just play the games, but the rest of us, those that became programmers as adults, were always the people who just had to ask the question “how the hell did they do that”?

I have been extremely privileged growing up in Norway during the 1980’s and 90’s, nowhere in the world (with exception of Germany, Sweden and Finland) was the demo scene stronger than in Norway. Even to this day we fill the viking ship annually with thousands of young programmers full of creativity (check out this site for tickets to The Gathering). So there can be little doubt that the “demo scene” is primarily a European phenomenon.

PS: if you are looking for talent then The Gathering should be the proverbial shangri-la !

But why? What is it good for?

Demo coding is one of the best ways of growing as a programmer and as a thinking individual. The problems you face (like tweening objects, calculating sprite paths, how one object stands in context to another, proportion, animation cycles – the works!) will help you in every avenue of life, including your personal life since it involved organization and thinking in terms of context. It will benefit you in the most unlikely of scenarios: Take an example from my life, I always wanted to code games, but I spent many years coding invoice systems, win32 services and all the “boring stuff”. But one day my employers wanted a 3d look and feel to their report, so i ended up using the skills i learned as a demo coder to complete tasks. Without it those reports would have been very dry, very dull and not very productive. So it turned out to be my creative side that made the difference, not my education (!) You dont learn stuff like this at the university.

No matter what your interests might be, from games programming to spreadsheets – you are bound to face the same mathematics and the same train of thought. But those that really succeed in these things are the programmers who took the time to really experiment with demo and games coding. Anyone can code a spreadsheet, but it’s the hacker that makes the numbers bounce πŸ˜‰

The Pascal Game Developer’s compo

Smart Mobile @ 98% complete

Smart Mobile @ 98% complete

When you think “pascal”, you think database driven business applications right? Well that’s just wrong. Delphi (which is the universal name for object pascal) earned that label because it made database programming simple in the early 90’s. But object pascal as a language is capable of so much more. So much so that databases become almost trivial in comparison. Remember all those high-speed dos games? (if you don’t, then get an emulator) A lot of those games were coded in turbo pascal. This was before we had full OOP and the might of the VCL at our fingertips.

It thus stands to reason that with all the power of the Delphi XE2 and the latest free-pascal compiler, that object pascal could knock out some serious games right? I mean — when compared to a commodore 64, Atari ST or Amiga?

Remember that the commodore 64 contained the same cpu-chip that powers most modern dishwasher’s today. Yet that little machine running at 1Mz with an 8bit bandwidth knocked out some pretty cool games! Now imagine what you could do with a computer 10.000 times faster, with 32 bit graphics, 24 bit sound and an IDE unlike anything we had back in the 80’s!

Well, unless you are reading this on a Pentium PC, that computer is what you have right now.

The gathering, Vikingship, Norway

The gathering, Vikingship, Norway

So… If they can do this on a 1mhz dishwasher, then surely we can do better right? With our dual-core processors, fifth generation 3d graphics chip-sets and latest operative systems?

Here are a couple of examples of what people can do with a commodore 64 (second video is from a modern PC, coded in machine code):

Instinct & Horizon C-64 Demo, 2008

And just how much brilliance can you pack into 64k of machine code?

Razor 1911 – my #1 demo group

And just to make it retro – here is the first Amiga demo i ever saw. This demo made me forget all about commodore 64 gaming, and ask the question “how”. This demo changed me from a gamer for a coder:

Doc – Demons are forever

Our mission is to follow javascript at every step. From it’s birth as HTML5 and onto it’s full evolution as a fully fledged multimedia system. We want to push the limits of what can be done under javascript to the full extent of it’s capabilities. And last but not least – to provide the infrastructure required for modern object pascal programmers to continue their hard earned experience and knowledge under a new platform. Javascript is quite alien to the average Delphi or FPC programmer, but with Smart you will be able to knock out apps with little effort.

Getting inspired

Today, the Pascal Game Developer competition started. And Smart was included in the list of allowed pascal compilers (jeey!). If you would like to use our product to push some limits then send us an email and we will return a preview version of smart (32bit) that you can use. You can use Smart as much as you want for the duration of the competition for free. While we are still in beta (with all the bells and whistles that pertains) there really is no compiler and IDE out there like Smart for webkit development!

Let’s push that border a couple of more inches, like pascal has always done πŸ™‚

Click here for the pascal game developer’s website

About the author


Jon Lennart Aasenden is a software architect at Optimale Systemer AS. He is currently the lead developer of Smart Mobile Studio and have been a strong supporter of Delphi and object pascal since the beginning. He is also involved in the evangelizing of object pascal in Norway and is by many called “a Delphi fundamentalist” due to his somewhat radical teaching methods. The views of the author is his own and does not reflect the policy of Optimale Systemer AS.

delphi demo fpc freepascal game gamedev games javascript Object Pascal OP4JS Pascal scene

Retro demo coded in Smart

Posted on 30.03.2012 by Jon Lennart Posted in Developers log 2 Comments
Parallax scrolling galore

Parallax scrolling galore

This is a small retro demo I put together last weekend. Believe it or not but it doesn’t use the HTML5 canvas display at all. Everything you see moving on the screen are actually controls (which in this case inherits from the lightweight TW3MovableControl, which is the base-class TW3CustomControl builds on).

You can test-drive the demo yourself here: Parallax demo

qrcode

Features

  • parallax scrolling
  • alpha blending
  • scroll-text with bitmap fonts
  • 3d rotated logo
  • hardware accelerated transformations

Note: This is a webkit only demo, so it will only run under Chrome or Safari (also iPad and iPhone is supported, but lacks sound).

The source

352 lines of uber-messy code, just like the good old days on the Amiga πŸ™‚

[sourcecode language=”delphi”]
unit Form1;

interface

uses w3system, w3graphics, w3ctrls, w3components, w3time,
w3forms, w3application, w3sprite3d, w3bmpfont;

const
CHAR_SIZE = 16;
CHARSET_FONT = ‘ !"#Β€%&/{}=_-\[]0123456789:;(|)?*abcdefghijklmnopqrstuvwxyz’;

type

TMenuLogo = Class(TW3Sprite)
Private
mDown: Boolean;
protected
Procedure InitializeObject;override;
public
Procedure UpdateBehavior(Const TimeId:Integer);override;
End;

TMenuBackground01 = Class(TW3Sprite)
protected
Procedure InitializeObject;override;
public
Procedure UpdateBehavior(Const TimeId:Integer);override;
End;

TFront = Class(TW3Sprite)
protected
Procedure InitializeObject;override;
public
Procedure UpdateBehavior(Const TimeId:Integer);override;
End;

TForm1=class(TW3form)
private
{ Private methods }
{$I ‘Form1:intf’}
FLogo: TMenuLogo;
FBack01: TMenuBackground01;
FTimer: TW3Timer;
FCounter: Integer;
FMyFont: TKromaskyBitmapFont;
FCredits: TW3Image;
FFontDone:Boolean;
FChars: Array of TW3Sprite;
FReady: Array of TW3Sprite;
FScrolled:Float;
FText: String;
FCharIndex:Integer;
FAudio: Variant;
FFront: TFront;
Procedure HandleUpdate(Sender:TObject);
procedure setupChars;
protected
{ Protected methods }
Procedure InitializeObject;override;
Procedure FinalizeObject;override;
Procedure StyleTagObject;reintroduce;virtual;
Procedure Resize;Override;
Procedure FormActivated;override;
Procedure FormDeActivated;override;
end;

Implementation

//############################################################################
// TFront
//############################################################################

Procedure TFront.InitializeObject;
Begin
inherited;
setTransformFlags(CNT_USE_POS);
Background.fromURL(‘res/tile_ground.png’);
Width:=96 * 32;
height:=96;
Transparent:=True;
end;

Procedure TFront.UpdateBehavior(Const TimeId:Integer);
var
mRange: Integer;
Begin
mRange:=application.Display.View.Width;
mRange:=(mRange div 96) * 96;
if X<=-(mRange) then
X:=0.0;
MoveX(-1.5);
Update3d;
end;

//############################################################################
// TMenuBackground01
//############################################################################

Procedure TMenuBackground01.InitializeObject;
Begin
inherited;
setTransformFlags(CNT_USE_POS);
Background.fromURL(‘res/gamebg02.png’);
Width:=960 * 2;
height:=480;
end;

Procedure TMenuBackground01.UpdateBehavior(Const TimeId:Integer);
Begin
if X<=-960 then
X:=0;
MoveX(-0.80);
Update3d;
end;

//############################################################################
// TMenuLogo
//############################################################################

Procedure TMenuLogo.InitializeObject;
Begin
inherited;
setTransformFlags(CNT_USE_POS or CNT_USE_SCALE or CNT_USE_ROTY);
Width:=422;
Height:=57;
mDown:=True;
Update3d;

Transparent:=True;
background.fromURL(‘res/parallax.png’);
end;

Procedure TMenuLogo.UpdateBehavior(Const TimeId:Integer);
Begin
if (TimeId mod 3)=0 then
Begin
case mDown of
True:
Begin
if Y<20 then
Begin
MoveY(0.50);
end else
mDown:=False;
end;
false:
Begin
if Y>10 then
Begin
MoveY(-0.50);
end else
mDown:=True;
end;
end;
update3d;
end else
Begin
RotateY(-1);
update3d;
end;
end;

//############################################################################
// TForm1
//############################################################################

function getXforChar(aChar:String):Integer;
var
xpos: Integer;
begin
if length(aChar)>1 then
xpos:=pos(aChar[1],CHARSET_FONT) else
if length(aChar)=1 then
xpos:=pos(aChar,CHARSET_FONT) else
exit;
result:=CHAR_SIZE * (xpos -1);
end;

Procedure TForm1.InitializeObject;
Begin
inherited;
{$I ‘Form1:impl’}
StyleClass:=”;

FTimer:=TW3Timer.Create;
FTimer.Delay:=1;
FTimer.onTime:=HandleUpdate;

asm
@FAudio = new Audio();
(@FAudio).autoplay=true;
(@FAudio).src = "res/Last Ninja wastelands.mp3";
end;

FBack01:=TMenuBackground01.Create(self);
FLogo:=TMenuLogo.Create(self);
FFront:=TFront.Create(self);
FMyFont:=TKromaskyBitmapFont.Create;

FText:=’Welcome to 1990* This is a nice retro demo coded in ‘
+ ‘Β€Smart Mobile StudioΒ€ Brought to you by Optimale Systemer AS ‘
+ ‘&&&&&&&& ‘;
FText:=lowercase(FText);
FCharIndex:=0;

Background.fromURL(‘res/ancientbg.png’);
w3_setStyle(tagRef,’background-repeat’,’repeat-x’);
w3_setStyle(tagRef,’background-size’,’auto 100%’);
End;

Procedure TForm1.FinalizeObject;
Begin
FLogo.free;
FBack01.free;
FFront.free;
inherited;
End;

Procedure TForm1.HandleUpdate(Sender:TObject);
var
x: Integer;
mSprite: TW3Sprite;
Begin
inc(FCounter);

FLogo.UpdateBehavior(FCounter);
FBack01.UpdateBehavior(FCounter);
FFront.UpdateBehavior(FCounter);

If FMyFont.Ready
and not FFontDone then
Begin
FFontDone:=True;
FCredits:=FMyFont.DrawAndMake(‘coded by quartex’);
FCredits.InsertInto(self.tagRef);
FCredits.Visible:=True;

FCredits.top:=Height – (FCredits.height + 10);
FCredits.left:=(Width div 2) – (FCredits.width div 2);
w3system.w3_Callback(self.resize,10);
end;

if length(FChars)>0 then
Begin
x:=-1;
repeat
inc(x);

mSprite:=FChars[x];
mSprite.moveX(-0.5);

if mSprite.x<=(-CHAR_SIZE) then
begin
FChars.Delete(x,1);
FReady.add(mSprite);
dec(x);
end else
mSprite.update3d;

until x>=high(FCHars);

end;

FScrolled+=0.5;
if FScrolled>=CHAR_SIZE then
begin
FScrolled:=0.0;
inc(FCharIndex);
if FCharIndex>Length(FText) then
FCharIndex:=1;

if FReady.length>0 then
begin
mSprite:=FReady[0];
FReady.Delete(0,1);
w3_setStyle(mSprite.tagRef,’backgroundPosition’,
‘-‘ + IntToStr(getXforChar(FText[FCharIndex])) +’px 0px’);
mSprite.x:=Width;
mSprite.y:=(Height div 2) – (CHAR_SIZE div 2);
mSprite.Update3d;
FChars.add(mSprite);
end;
end;
end;

procedure TForm1.setupChars;
var
cnt: Integer;
x: Integer;
mChar: TW3Sprite;
begin
if FChars.length<1 then
Begin
cnt:=width div CHAR_SIZE;
if (cnt * CHAR_SIZE) < width then
inc(cnt);
inc(cnt);

for x:=0 to cnt-1 do
Begin
mChar:=TW3Sprite.Create(self);
mChar.setTransformFlags(CNT_USE_POS);
mChar.background.fromUrl(‘res/fnt16x16.png’);

w3_setStyle(mChar.tagRef,’backgroundPosition’,’0px 0px’);
mChar.x:=-CHAR_SIZE * 2;
mChar.width:=CHAR_SIZE;
mChar.height:=CHAR_SIZE;
//mChar.color:=clRed;
mChar.Transparent:=True;
mChar.visible:=true;
mChar.update3d;
FReady.add(mChar);
end;
end;
end;

Procedure TForm1.FormActivated;
Begin
inherited;
setupChars;
FTimer.Enabled:=True;
end;

Procedure TForm1.FormDeActivated;
Begin
FTimer.enabled:=False;
inherited;
end;

Procedure TForm1.Resize;
var
dx: Integer;
Begin
inherited;
dx:=(width div 2) – (FLogo.width div 2);
FLogo.setBounds(dx,10,FLogo.Width,FLogo.Height);
FFront.setBounds(0,Height-FFront.height,FFront.width,FFront.height);
FBack01.top:=FFront.top – FBack01.height;
if FCredits<>NIl then
begin
FCredits.top:=Height – (FCredits.height + 10);
FCredits.left:=(Width div 2) – (FCredits.width div 2);
end;
end;

Procedure TForm1.StyleTagObject;
Begin
// Custom styling
End;

end.
[/sourcecode]

demo parallax

Sprite3d converted to Smart

Posted on 23.03.2012 by Jon Lennart Posted in Developers log 2 Comments

I am happy to report that the award winning HTML5 3d system Sprite3d has been converted to Object Pascal and will ship with Smart Mobile Studio. Sprite3d is a fantastic javascript library which allows you to perform advanced 3d transformations on ordinary HTML elements. Since CSS 3d is hardware accelerated both on mobile and desktop browsers -the results often outperform drawing graphics using the canvas object.

As an example of what you can do with Sprite3d have a look at the following demo (written by the Sprite3d author). Keep in mind that this is not webGL It uses nothing but CSS and javascript and all the objects are ordinary DIV tags.

Under Smart Mobile Studio, using Sprite3d to rotate a button in 3d-space is as simple as:

FSprite:=TW3Sprite3d.Create(button1);
try
  FSprite.SetTransformOrigin(button1.Width div 2, button1.height div 2);
  FSprite.RotateY(1.5);
  FSprite.RotateZ(-0.5);
  FSprite.Update3d;
finally
  FSprite.free;
end;

The exciting part is that you can apply these transformations to any Smart control. While it is highly doubtful that a spinning edit-box will be of much use in serious business applications, the effects could be leveraged as a means to add life to otherwise static interfaces (options that scale in/out, drop down lists that rotate on close, buttons that move as a response to touch) – and last but not least, it opens up for some interesting multimedia possibilities.

About the author


Jon Lennart Aasenden is a software architect at Optimale Systemer AS. He is currently the lead developer of Smart Mobile Studio and have been a strong supporter of Delphi and object pascal since the beginning. He is also involved in the evangelizing of object pascal in Norway and is by many called “a Delphi fundamentalist” due to his somewhat radical teaching methods. The views of the author is his own and does not reflect the policy of Optimale Systemer AS.

feature sprite3d sprites

Pages

  • About
  • Feature Matrix
  • Forums
  • News
  • Release History
  • Download
  • Showcases
    • The Smart Contest 2013, Round 1 – Graphics
  • Store
  • Documentation
    • Creating your own controls
    • Debugging, exceptions and error handling
    • Differences between Delphi and Smart
    • Get the book
    • Getting started
      • Introduction
      • Local storage, session storage and global storage
      • Application architecture
      • The application object
      • Forms and navigation
      • Message dialogs
      • pmSmart Box Model
      • Themes and styles
    • Layout manager
    • Networking
      • Loading files
      • TW3HttpRequest
      • TW3JSONP
    • Prerequisites
    • Real data, talking to sqLite
    • System requirements
    • Project types
      • Visual project
      • Game project
      • Console project

Archives

  • December 2019
  • December 2018
  • November 2018
  • July 2018
  • June 2018
  • February 2018
  • September 2017
  • April 2017
  • November 2016
  • October 2016
  • September 2016
  • April 2016
  • March 2016
  • January 2016
  • October 2015
  • September 2015
  • July 2015
  • April 2015
  • January 2015
  • December 2014
  • October 2014
  • September 2014
  • August 2014
  • July 2014
  • June 2014
  • March 2014
  • February 2014
  • January 2014
  • December 2013
  • November 2013
  • October 2013
  • August 2013
  • July 2013
  • June 2013
  • May 2013
  • April 2013
  • March 2013
  • February 2013
  • January 2013
  • December 2012
  • November 2012
  • August 2012
  • July 2012
  • June 2012
  • May 2012
  • April 2012
  • March 2012
  • February 2012
  • January 2012
  • November 2011
  • October 2011
  • September 2011

Categories

  • Announcements (25)
  • Developers log (119)
  • Documentation (26)
  • News (104)
  • News and articles (16)

WordPress

  • Register
  • Log in
  • WordPress

Subscribe

  • Entries (RSS)
  • Comments (RSS)
  • Prev
  • 1
  • 2
  • 3
  • 4
  • 5
  • …
  • 7
  • Next
Β© Optimale Systemer AS