Jump to content


Photo

Game Demo


  • Please log in to reply
10 replies to this topic

#1 Czar

Czar
  • Members
  • 165 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.

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

Attached Files


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

#2 Igor Savkic

Igor Savkic
  • Members
  • 188 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
  • 318 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

Laksekjønn
  • Members
  • 455 posts

Posted 04 August 2017 - 01:53 AM

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

  • Czar likes this

#5 Czar

Czar
  • Members
  • 165 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

Laksekjønn
  • Members
  • 455 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

Czar
  • Members
  • 165 posts

Posted 05 August 2017 - 02:26 AM

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

#8 Czar

Czar
  • Members
  • 165 posts

Posted 22 August 2017 - 12:51 PM

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://numberworksnw...haos/index.html


junglechaos.jpg
  • ielite, Nico Wouterse, Igor Savkic and 1 other like this

#9 ielite

ielite
  • Members
  • 723 posts

Posted 22 August 2017 - 10:41 PM

very nice

#10 Igor Savkic

Igor Savkic
  • Members
  • 188 posts

Posted 23 August 2017 - 12:37 AM

Just curious, how do you animate their hands, do you have sprites for every move and then change between images?
Also for rotation (while jumping), do you work with 2d images or have 3d images?

#11 Czar

Czar
  • Members
  • 165 posts

Posted 23 August 2017 - 01:50 AM

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




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users