Jump to content
Sign in to follow this  
Czar

Game Demo

Recommended Posts

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.

 

gameshot.jpg

 

 

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.

 

spritesheet1.png

 

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.

 

laser.png

 

var missile : TMissile;

for missile in FMissiles do

begin

var idx := missile.Frame mod 9;

Canvas.Save;

Canvas.Translate(missile.x+16, missile.y+16);

Canvas.Rotate(missile.ang);

canvas.DrawImageF(FImgMissile,

(idx mod 3)*32, (idx div 3)*32, 32, 32,

-16,

-16,

32, 32);

Canvas.Restore;

end;

 

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

asm

window.onkeydown=function(e)

{

TCanvasProject.KeyDownEvent(Self,e.keyCode);

}

window.onkeyup=function(e)

{

TCanvasProject.KeyUpEvent(Self,e.keyCode);

}

end;

KeyDownEvent(0);

KeyUpEvent(0);

 

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

GameDemo.zip

Share this post


Link to post
Share on other sites

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!

Share this post


Link to post
Share on other sites

IMHO, to update the canvas animation you should use requestAnimationFrame for smoother animations

 

procedure TCanvasProject.ApplicationStarting;
begin
inherited;
...
--> w3_RequestAnimationFrame(DoResize);

 

 

Share this post


Link to post
Share on other sites

@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.

Share this post


Link to post
Share on other sites

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.com/resources/requestanimationframe/

Share this post


Link to post
Share on other sites

As part of our exploration of SmartMS I decided to convert a very old game that I wrote back in 2002 using DelphiX. No PNGs and the slowest computers were pentium 200mhz. It was interesting to see how we dealt with really old, slow computers to ensure the Dudes did not "fall" through the platform. Those issues don't really exist any more with the speed of current machines and browsers.

 

With the conversion I literally copied large sections of Delphi code into SmartMS and then adjusted what was required. I also tidied up a few poor programming decisions and improved some of the graphics. Can I get a bit cheer for PNGs? All the images were originally in 8bit Bitmap format with Fuchsia as the transparent colour. We had little tricks to ensure you didn't end up with a Fuchsia tinted fringe.

 

This game was built using Canvas and used the same framework as the Game Demo at the start of this thread. There are a few problems with the placement of visuals so it may not look right on your browser. I may tidy that up later. Our games are written to be played in approximately 70 seconds. And they must appeal to kids from 5 to 15 years old. Jungle Chaos has been a popular game in our centres for the last 15 years. The total conversion including upgraded visuals, tweaking the game play and solving various programming challenges took approx two and a half working days. Not too bad.

 

http://numberworksnwords.com/cloud/junglechaos/index.html

 

 

junglechaos.jpg

Share this post


Link to post
Share on other sites

They are 3d rendered images - i.e., a 2d sprite sheet. I used 3dMax to render the images. The little dudes represents the limits of my 3d ability :D

 

The "Dude" has a number of animations, e.g.,walking, falling, spinning captured. The animation just updates the frame after certain amount of milliseconds.

 

dudeupdown.png

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×