Jump to content


Game Demo

  • Please log in to reply
6 replies to this topic

#1 Czar

  • Members
  • 131 posts

Posted 02 August 2017 - 04:38 AM

When I picked up Delphi 2 many many years ago my main goal was to program games. Purely as a hobby as I never intended to program for a living.

For many years I made games using DelphiX and later DanJetX and OmegaDX9. Smart Mobile Studio represents an awesome opportunity to create games and animated graphics for browsers, tablets and phones. Initially I thought it would be a breeze converting some of my older games to SMS but I quickly ran into a myriad of challenges. Mainly due to my lack of understanding.

I set about trying to make a demo that demonstrated techniques that I need in order to port some of my games. First I tried running as many demos as I could but all of them lacked elements of what I needed. I found the missile command demo very useful although due to a lack of documentation it can be difficult to understand certain parts of it. The Missile Command demo lacked a number of important elements. There was no keyboard interaction and none of the sprites were being rotated or otherwise manipulated.

I have managed to solve my challenges because Jon and others, here on the forum, are patient enough to answer some of my questions. For that reason I decided to post my Game Demo here and also explain a few of the challenges that I encountered so that others can learn from it.


Canvas vs. Form
You can create a game in either canvas mode or using a tW3form. The canvas is faster and similar to a DirectX surface and the Form is the equivalent of using a Delphi Form with VCL components. Use the canvas.

My Requirements
SpriteSheet - the easiest way to animate a sprite is to use a spritesheet that contains all the animation frames.


Rotation - This was a real bugbear for me. How to rotate the image on the screen. It turns out to be pretty simple but there were no examples available that demonstrated this techinque.

Here is an example. The spritesheet is 3x3, i.e., there are 9 cells of animation. The current cell is drawn to the canvas. In this code the missile is drawn with the ability to be rotated. First we save the canvas's current settings. We then translate the point of origin to the centre of the image (cell). Each cell is 32x32 pixels so we step in 16 from the left and top. Now we rotate to the current angle and draw the image to the screen. Finally we restore the canvas to its saved state.


var missile : TMissile;
for missile in FMissiles do
var idx := missile.Frame mod 9;
Canvas.Translate(missile.x+16, missile.y+16);
(idx mod 3)*32, (idx div 3)*32, 32, 32,
32, 32);

note: the graphics resources appear to be case insensitive when you run from the IDE. However, make sure you use the correct case when referencing the graphics files otherwise you will have errors when you open the index.html on your website.

Keyboard - the game examples that I found were all mouse friendly and did not require keyboard interaction. For my demo I want to be able to move a spaceship around using the arrow keys and be able to fire using the space bar.

It turns out that the keydown and keyup events are not functioning correctly in SMS. I had to use Sascha's work around to get those events to work

// keydown doesn't work at the present time this little work around solves the problem

It is possible to respond to the keys in the keydown event. The problem is when the player is holding down the space bar to shoot and then they hit one of the arrow keys. Now the spacebar is no longer sending a keydown event. The work around is to store when a key goes down and when it comes back up. If the player holds down the spacebar the Shooting boolean is set, when they let go the keyup event sets the shooting boolean back to false. This system works nicely.

I based my demo on the Missile Command demo as it was nicely set up and I could learn some new programming techniques. However, unlike that demo I did not want my Game Demo to be limited to a certain Frame Per Second. Instead I used the LastFrameTime to calculate distances etc. So all sprites move on a basis of pixels per time.

I hope this Games Demo helps people over come some basic challenges and I would be keen to hear feedback.

Note: I am using current beta RTL - unsure if it will compile with older RTL.
GameDemo - live

Attached Files

  • Jørn E. Angeltveit, Nico Wouterse, BobLawrence and 3 others like this

#2 Igor Savkic

Igor Savkic
  • Members
  • 169 posts

Posted 02 August 2017 - 09:44 AM

Thanks for the post, it's quite informative to us not involved in games development.
  • Czar likes this

#3 Cipher Diaz

Cipher Diaz
  • Administrators
  • 313 posts

Posted 02 August 2017 - 04:46 PM

First, awesome post! Inspiring and cool (and love the graphics man!) About the keyboard stuff, this is very simple in the new RTL (that you use here). If you look in the unit SmartCL.Components, there is a type called "TW3CreationFlags". You might remember from Delphi that forms have something called CreateParams? In Delphi it looks like this: procedure CreateParams(var Params: TCreateParams); override; We might adopt a similar approach later, but right now our version looks like this: class function CreationFlags: TW3CreationFlags; virtual; If you override this function you can set some low-level stuff to control things like input. In HTML5 a value needs to be set for a DIV to catch keyboard events. So to make your control(s) get input events, simply add the "cfKeyCapture" set-value. Here are the values you can use on any control: Note: These flags drastically alters the behavior of a control, please make sure you study and understand these before altering them. *) TW3CreationFlags = set of ( cfIgnoreReadyState, // Ignore waiting for readystate cfSupportAdjustment, // Controls requires boxing adjustment (default!) cfReportChildAddition, // Dont call ChildAdded() on element insertion cfReportChildRemoval, // Dont call ChildRemoved() on element removal cfReportMovement, // Report movements? Managed call to Moved() cfReportResize, // Report resize? Manages call to Resize() cfAllowSelection, // Allow for text selection cfKeyCapture // assign tabindex, causing the control to issue key and focus events ); Simply override the function for your class like this: Class function TMyContainer.CreationFlags: TW3CreationFlags; begin result := inherited CreationFlags(); Include(result, cfKeyCapture); end; And now you the OnKey-xyz events will fire. The reason its isolated like this is because we didnt want to activate it everywhere. Under HTML5 it can cause some confusion if every single element has it -- also events behave different (propagation).. Well, hope it helps!
  • Czar likes this

#4 Laksekjønn

  • Members
  • 428 posts

Posted 04 August 2017 - 01:53 AM

IMHO, to update the canvas animation you should use requestAnimationFrame for smoother animations
procedure TCanvasProject.ApplicationStarting;
--> w3_RequestAnimationFrame(DoResize);

  • Czar likes this

#5 Czar

  • Members
  • 131 posts

Posted 04 August 2017 - 02:15 AM

@Laksekjønn can you explain that some more? What does it do and what should I notice?

I put w3_RequestAnimationFrame(DoResize); into the ApplicationStarting procedure but I wasn't able to see an effect.

#6 Laksekjønn

  • Members
  • 428 posts

Posted 05 August 2017 - 01:41 AM

the biggest advantage of requestAnimationFrame is request an animation frame only when it is needed. Let's say you show a static black canvas, you should get 0 fps because no new frame is needed. But if you're displaying an animation that requires 60fps, you should get that too. requestAnimationFrame just allows to "skip" useless frames and then save CPU.

Details in http://creativejs.co...animationframe/
  • Czar likes this

#7 Czar

  • Members
  • 131 posts

Posted 05 August 2017 - 02:26 AM

@Laksekjønn the link is perfect thanks - explains a lot.

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users