Tutorial 42 - Pointers

Written By Akki On Friday, November 16, 2007

Tutorial 42 - Pointers

Pointers

Ah, the wonderful world of pointers! Have you ever read about them or heard about them? The cause of programmer's nightmares all around the world. Even if PPL allow you to live without them, you still can use them to expand the power of your programs.

Lets start with string pointers. Strings in PPL are stored pretty much like any other strings in other programming languages. Each byte represents a character. If you define a string, you can later on access its pointer value and go to a specific character by adding a value to it.

s$ = "HELLO WORLD";
i$ = &s$ + 3;
ShowMessage(@i$);

The following code will display "LO WORLD" in a dialog. The value of variable i$ will be the pointer location of s$ in memory plus the value 3. Now i$ is a simple numerical variable, nothing more. We need to convert it back into a string. The @ operator is used to convert a numerical value into memory content.

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 41 - The physic engine

Written By Akki

Tutorial 41 - The physic engine

The physic engine

Our world is made of physic, everything is physic! Gravity pushes every object to the ground, every step we take involves friction with the surface our shoes come in contact with, wind blows and pushes leaves around and balls bounces from the ground and walls with different elasticity. When applied to a game, physics can add more realism and can add possibilities you thought were too hard to code. PPL comes with a 2D automated physic engine. When I say automated I mean it, you only need to set the mass of a sprite, set the global gravity and the physic will take care of pushing the object down. Objects can bounce back and forth by simply assigning an elasticity value. The physic is far from an advanced one that supports object deformation on collision and such but it can do a very good job simplifying your life while developing your game.
Lets first start by reviewing the principal functions used by the physic engine:

SetSpriteMass(Sprite$, Mass);

The mass is a percentage value that is compared to the other sprites with physic. A sprite with 0.5 mass will weight half the weight of a sprite with a mass of 1.0.

SetSpriteElasticity(Sprite$, Elasticity);

The elasticity value is a percentage compared to the other sprites. The bigger the value the more rebound will be applied when the sprite collides with another sprite.

SetSpriteFriction(Sprite$, Friction);

The friction is the amount of friction in percentage applied to reduce the movement speed of the sprite when it collides with another sprite.

SetGravity(Gravity);

This function will set the global gravity of the sprite engine, the value of the gravity is applied to the sprites movement speed each cycle. Default gravity is around 0.1.

SetFriction(Friction);

Set the global friction that is applied to sprite's movement speed each cycle. The default friction value is 0.00025.

There are options that need to be activated for the physic engine to consider moving the objects around. The first one is the SO_KINETIC to active the physic engine on the sprite itself. The second one is the SO_BOUNCE, it will make the sprite bounce around from other sprites. The bounce force is calculated based on the Elasticity of the sprite. Sprites must have the SO_COLLIDECHECK option set to them for bouncing to occur. You can have your sprites bounce from the screen edges by setting the SO_BORDER option. Most of the sprites you will want to bounce around will be of oval shape, you will want to set the SO_OVAL option for the physic engine to bounce the sprite like a real oval shaped object.

Lets review the bounce.ppl demo that comes with PPL. This demo involves 5 basketball balls bouncing around from the screen edges and from each other. In this example we create 5 sprites with the basketball ball image and the we set the options of each sprite to oval shape, collision checking, pixel checking and border collision check.

// Set global gravity.
SetGravity(0.1);
// Set global friction.
SetFriction(0.005);

i$ = 0;
while (i$ < 5)
// Load ball sprite from disk.
s$ = loadsprite(AppPath$ + "ball.bmp", G_RGB(255, 0, 255), 1, 0, NULL);

// Activate pixel perfect collision detection.
AddSpriteOption(s$, SO_OVAL | SO_CHECKCOLLIDE | SO_PIXELCHECK | SO_BORDER | SO_KINETIC);

// Make the balls collide and never go over another.
SetSpriteCollide(s$, "BALL");
SetSpriteId(s$, "BALL");

repeat
MoveSprite(s$, random(g_width - 40), random(64));
ProcessSprites(1, 0);
until (Collide(s$, SpriteX(s$), SpriteY(s$), nx$, ny$) == NULL);

// Set ball elasticity.
SetSpriteElasticity(s$, 0.01);

// Set some friction when the balls collide.
SetSpriteFriction(s$, 0.01);

// Set sprite's weight.
SetSpriteMass(s$, 0.5);

// Set the maximum velocity to 10 pixels.
SetSpriteVelLimits(s$, 0, 10);

i$++;
end;

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 40 - Form Options Quick Reference

Written By Akki

Tutorial 40 - Form Options Quick Reference

Form Options Quick Reference (by Brad Manske)

Each of the options are listed below along with the effect that it has on the form.

Dialog Form
Default: Off
When selected, the form will be created using a call to NewDlg to create the window. If not selected, then NewForm will be used to create the window if it is full screen, DefaultForm is selected in styles and there are no extended styles. If these conditions are not met, then the NewFormEx function will be used to create the window.

Generate Library
Default: Off
When selected, the form will create PPL source code that can be included in with a larger project. If not selected, the form will have a WinMain function indicating the entry point for the project. It is possible to create a stand alone program in a single form file with this option deselected.

Simplified Event Handling
Default: On
When selected, PPL will route the windows messages to the correct handler functions. If not selected, then the more traditional case table type logic is needed to decode and process the messages sent to the handler functions.

Extended Event Code
Default: On
When selected, PPL will include code in the Simplified Event Handlers to do some of the more
common decoding of the windows messages. If not selected, the code will be left off. To find the included code look in SWAPI.PPL for the #define for HandleEventParms.

Use Namespace
Default: On
When selected, the form will include the #NameSpace command in the generated PPL code. This will force global variables and controls into their own namespace to avoid items named the same on multiple forms. If not selected, then all global variables and controls will be placed into the global NameSpace.

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 39 - PPL Assembler

Written By Akki

Tutorial 39 - PPL Assembler

PASM from the Beginning (by Brad Manske)

"PASM can wait till after 1.0" was my reaction when I heard the plans to include a cross platform assembler with PPL. While it was not a lot of code, the complexity was way up there. So that it could run on multiple processors it had to be a virtual processor that was compiled to. There were 36 addressing modes for 22 assembly instructions that would potentially compile to a series of instructions for 2 different processors. The project required complex and intimate knowledge of the processors and the testing challenge was not going to be easy.

My earliest e-mail on this project (that I kept) is dated the 20th of March 2004. We had already worked together for almost 2 years when the topic came up. There is no backing down from a complex technical challenge, so even though the pressure to release 1.0 was high, PASM went forward. This article will introduce you to PASM and it just may be the raw speed boost your code needs. I will start off with some explanation for the people who have not had much exposure to assembly language. Assembly is a text representation of the 1s and 0s that the computer actually executes. For example:

X$ = 10;

This would be an instruction to move the value 10 into the variable X$:

move x, 10

Sound simple? Well, yes, if the processor supports moving a value into memory without going through a register first. And if the value fits in a 32 bit register (Windows CE requires a 32 bit processor). And, etc...

This is the reason that PASM uses a virtual processor internally. We couldn't guarantee that these conditions would be met for each processor since all of the code written for PASM must run on all of our supported platforms.

The PASM virtual processor is made up of 4 general purpose registers named R0, R1, R2 and R3. There are more specialized registers like the Stack Pointer (SP) and the Stack Frame (SF). The Arithmetic and Logic unit of our processor is a simplified RISC (Reduced Instruction Set Computing) like design. The instruction set consists of about 22 different assembly operations. This isn't much compared to the hundreds of instructions supported by some processors, but there are 36 addressing modes to offset the simplicity of the instruction set.Here is a quick look at the MOV instruction and the addressing modes that it supports. For 32 bit values:

mov Register, Value move from Value to Register
mov Absolute, Value move from Value to Absolute address
mov [Register], Value move from Value to Indexed Register
mov [Absolute], Value move from Value to Indexed Absolute address
mov Register, Register move from Register to Register
mov Register, [Register] move from Indexed Register to Register
mov [Register], Register move from Register to Indexed Register
mov [Register], [Register] move from Indexed Register to Indexed Register
mov Absolute, Register move from Register to Absolute address
mov [Absolute], Register move from Register to Indexed Absolute address
mov Register, [Register+offset] move from Index+Offset Register to Register
mov [Register+offset], Register move from Register to Index+Offset Register
mov [Register+offset], [Register+offset] move from Index+Offset Register to Index+Offset Register
mov Absolute+offset, Register move from Register to Absolute+Offset address
mov Absolute+offset, Value move from Value to Absolute+Offset address
mov [Absolute+offset], Register move from Register to Index+Offset Absolute address
mov [Absolute+offset], Value move from Value to Index+Offset Absolute address
mov [Register+offset], Value move from Value to Index+Offset Register

MOV also supports a size modifier for 8 bits (byte) and 16 bit (word) values:

mov size Register, Register move size from Register to Register
mov size Register, [Register] move size from Indexed Register to Register
mov size [Register], Register move size from Register to Indexed Register
mov size [Register], [Register] move size from Indexed Register to Indexed Register
mov size Absolute, Register move size from Register to Absolute address
mov size Absolute, Value move size from Value to Absolute address
mov size [Absolute], Register move size from Register to Indexed Absolute address
mov size [Absolute], Value move size from Value to Indexed Absolute address
mov size Register, Value move size from Value to Register
mov size [Register], Value move size from Value to Indexed Register
mov size Register, [Register+offset] move size from Index+Offset Register to Register
mov size [Register+offset], Register move size from Register to Index+Offset Register
mov size [Register+offset], [Register+offset] move size from Index+Offset Register to Index+Offset Register
mov size Absolute+offset, Register move size from Register to Absolute+Offset address
mov size Absolute+offset, Value move size from Value to Absolute+Offset address
mov size [Absolute+offset], Register move size from Register to Index+Offset Absolute address
mov size [Absolute+offset], Value move size from Value to Index+Offset Absolute address
mov size [Register+offset], Value move size from Value to Index+Offset Register

A few quick note about the notation above. The brackets [] above mean that the value of the expression inside the brackets is the memory location that will be operated on. Register is a register R0 to R3 or one of the special registers. Absolute, is a number representing a specific memory location. Offset an integer value that allows you to adjust the value of the memory address operated on without the need to modify the base.
Here is a very simple example:

#include "console.ppl"

func WinMain;
InitConsole;
ShowConsole;

new(startVal$, tint);
new(endVal$, tint);

StartVal$ = 0;
EndVal$ = 0;

asmCall$ = asm(1024, );

callasm(asmCall$, 20, 30);

writeln("Test "+ startVal$ + ", "+ endVal$);

freeasm(asmCall$);

free(startVal$, endVal$);

return(true);
end;


If you read my previous articles, you know that I'm a fan of using the console for my examples, so it should be no surprise that I first include the console. Next I declare some variables in the PPL memory space outside of PASM. Next is the assembly code followed by the CallASM instruction. Some values are written and the assembly code and variables are freed. When compiled, the call to ASM takes 2 arguments the first being the size of the byte buffer that holds the assembled code and the second is the string of assembly instructions. The buffer is specified in bytes and a multiplier is used on the buffer size depending on what you are doing.

For example, by running your code under debug, it is possible to step through and break on assembly instructions. In order to do this, extra machine code instructions are inserted to support doing this so the buffer must be expanded. It also means that your code will execute slower under debug than it will in run mode. The buffer is created at run time and the assembler runs against the 2nd argument which is the text with all of the assembly instructions. So keep in mind that if you make a change to the assembly code, any errors will not be found until run time. It also means if you plan on using the assembler you may want
to place your ASM instructions at startup and keep them for the duration of the program so that the code is not reassembled during the execution of your program when you really need the speed.

The CallASM instruction invokes the code created in the buffer by the ASM command. CallASM can take additional arguments that will be passed into the assembly code as parameters. The parameters are placed into an AARGS$ array and the size of the array is placed into AARGSCOUNT$. Each of the parameters are treated as a 4 byte (32 bit) value. So the value of 20 is at [AARGS$] and the value of 30 is at [AARGS$+4].

The line ":main" above indicates the entry point to your assembly code. This is a label and is used as the target in jump instructions. The line "#DEASM" above instructs the ASM instruction place the actual assembly instruction for your processor to be placed into the DebugLog file. This does take extra time, so it shouldn't be used in production programs. The #debugoff pragma can be used to disable this for the entire project. Here is a simple example when using #DEASM. The 2 lines from above:

mov StartVal$, 1
mov EndVal$, 2

On Intel processors are translated into:

mov edi, D45B28h(STARTVAL$)
mov [edi], 01h
mov edi, D45B98h(ENDVAL$)
mov [edi], 02h


On Arm processors are translated into:

ldr r9, 34C9B0h(STARTVAL$)
ldr r10, #01h
str r10, [r9]
str r10, #01h
ldr r9, 34CA40h(ENDVAL$)
ldr r10, #02h
str r10, [r9]
str r10, #02h

The lines from the PASM example above:

savesp
pplpush [AARGSCOUNT$]
ppl showmessage


Show an example of saving the position on the stack pushing some arguments onto the stack where ppl can get to it then calling a PPL function. Here is another example:

savesp
pplpushstr tstStr1$
pplpushstr tstStr2$
pplpushstr tstStr3$
ppl concat
pplpull


In this example, the stack pointer is saved, all of the required arguments are placed onto the stack and the PPL concat function is called to concatenate the strings together. The stack is restored to its previous state after the PPL call, then the address of the new string is pulled from the stack. The new string is created in a new memory space that the garbage collector will automatically clean up from. I'll leave you with one more example. This example demonstrates the usage of Jump instructions and the use of an assembly procedure. The entry point is at ":main". It tests the number of arguments passed into the assembly code to see if there is only one. In this case there is only one so the value of 20 is passed to the function "!asmCalc". As in high level code, the string in parenthesis becomes a variable for the function. The "Var FinSum" instructions declares a local var for use within the function. The function then calculates the Fibonacci series on the number passed to it adding all of the numbers from n + (n-1) + ... + 2 + 1.

#include "console.ppl"

func WinMain;
InitConsole;
ShowConsole;

new(startVal$, tint);
new(endVal$, tint);

asmFib$ = asm(1024, );

t$ = tick;

callasm(asmFib$, 20);

writeln("Fibbon("+ startVal$ + ")="+ endVal$ + " time =" + (tick - t$));

freeasm(asmFib$);

free(startVal$, endVal$);

return(true);
end;


Play with PASM a while and let us know what you think in the Forums. In the next newsletter, I will address some more advanced examples.

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 38 - Encryption strings easily.

Written By Akki

Tutorial 38 - Encryption strings easily.

Encrypting strings in PPL.

What if you want to protect a file from sneaky eyes? The best solution is to encrypt the file using a very strong password that only you know about. PPL comes with a nice function called Encrypt() that can do this for you very easily.

s$ = "HELLO WORLD!";
Encrypt(s$, -1, "MYKEY", True);
ShowMessage(s$);
Encrypt(s$, -1, "MYKEY", False);
ShowMessage(s$);

In the following example we encrypt the string “HELLO WORLD!” using an encryption algorythm that uses the key “MYKEY” to encode the result string. The last parameter of the Encryt() function specify if we are encrypting or decrypting the string, true means encryt and false means decrypt. It is always a good idea idea never to leave a key as a regular string in your code even though the .ppc file that PPL generates is encrypted and compressed, it can be easier for a hacker to decode. Try to build your key string using code with mathematical code if possible.

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 37 - Compressing strings in PPL.

Written By Akki

Tutorial 37 - Compressing strings in PPL.

Compressing strings.

The Pro version of PPL comes fully loaded with different compression and decompression methods from two simple functions: Compress() and UnCompress(). Here are the different compression methods supported by PPL:

_RLE

RLE, or Run Length Encoding, is a very simple method for lossless compression. It simply replaces repeated bytes with a short description of which byte to repeat, and how many times to repeat it.

Though simple and obviously very inefficient fore general purpose compression, it can be very useful at times (it is used in JPEG compression, for instance).

_HUFFMAN

Huffman encoding is one of the best methods for lossless compression. It replaces each symbol with an alternate binary representation, whose length is determined by the frequency of the particular symbol.

Common symbols are represented by few bits, while uncommon symbols are represented by many bits.

The Huffman algorithm is optimal in the sense that changing any of the binary codings of any of the symbols will result in a less compact representation. However, it does not deal with the ordering or repetition of symbols or sequences of symbols.

_LZ

There are many different variants of the Lempel-Ziv compression scheme. The Basic Compression Library has a fairly straight forward implementation of the LZ77 algorithm (Lempel-Ziv, 1977) that performs very well, while the source code should be quite easy to follow. The LZ coder can be used for general purpose compression, and performs exceptionally well for compressing text. It can also be used in combination with the provided RLE and Huffman coders (in the order: RLE, LZ, Huffman) to gain some extra compression in most situations.

Lets take the following code:

in$ = LoadStr(AppPath$+ “MyFile.txt”, insize$);
New(out$, insize$ * 2);
outsize$ = Compress(_RLE, in$, out$, insize$);


This code will load file MyFile.txt into variable in$, return the size in bytes in variable insize$. We then need to create an output buffer that is at least equal or preferably greater that the original input buffer. We then apply the RLE compression method to in$ and outputting the result in the out$ variable returning the new size of the out$ variable in outsize$.

You can then decompress the out$ buffer to a new newin$ buffer with the following:

New(newin$, outsize$ * 2);
newinsize$ = Compress(_RLE, out$, newinsize$, outsize$);

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 36 - Regular Expressions in PPL

Written By Akki

Tutorial 36 - Regular Expressions in PPL

Regular Expressions (Regex):

From www.regular-expressions.info:

“A regular expression (regex or regexp for short) is a special text string for describing a search pattern. You can think of regular expressions as wildcards on steroids. You are probably familiar with wildcard notations such as *.txt to find all text files in a file manager. The regex equivalent is .*\.txt . But you can do much more with regular expressions. In a text editor like EditPad Pro or a specialized text processing tool like PowerGREP, you could use the regular expression \b[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]\b to search for an email address. Any email address, to be exact. A very similar regular expression (replace the first \b with ^ and the last one with $) can be used by a programmer to check if the user entered a properly formatted email address. In just one line of code, whether that code is written in Perl, PHP, Java, a .NET language or a multitude of other languages.”

PPL supports a variety of expressions like:

\Quote the next metacharacter
^ Match the beginning of the string
. Match any character
$ Match the end of the string
| Alternation
() Grouping (creates a capture)
[] Character class

==GREEDY CLOSURES==

* Match 0 or more times
+ Match 1 or more times
? Match 1 or 0 times
Match at least n times
Match at least n but not more than m times

==ESCAPE CHARACTERS==

\t tab (HT, TAB)
\n newline (LF, NL)
\r return (CR)
\f form feed (FF)

==PREDEFINED CLASSES==

\l lowercase next char
\u uppercase next char
\a letters
\A non letters
\w alphanimeric [0-9a-zA-Z]
\W non alphanimeric
\s space
\S non space
\d digits
\D non nondigits
\x exadecimal digits
\X non exadecimal digits
\c control charactrs
\C non control charactrs
\p punctation
\P non punctation

To search a string using regular expression in PPL you will use the Search() function. You can also make sure that the string is an exact match of the regular expression you are providing with the Match() function.

Let's take the following example:

string$ = "Bill Clinton";
expr$ = "^(Bill|George|Renald) (Clinton|Bush|Reagan)$";
Search(expr$, string$, b$, e$);
ShowMessage(b$ + "," + e$);

The expr$ variable contains an expression that says, if the first word is either Bill, George or Renald and that the string ends with Clinton, Bush or Reagan, we have a match. “Bill Clinton” will be the beginning of our result string, b$ and “” will be our ending string e$.

i$ = 0;
while(i$ <= subexpcount - 1)
subexp(string$, i$, begin$, len$);
ShowMessage("SubExp " + i$ + " = " + begin$ + "," + len$);
i$++;
end;

In the previous example, we check each sub expression to see what matched in the string string$ and where it started and how many characters the sub expression took from string$.
Sub expression 0 will return “Bill Clinton” for a length of 12 because it do the whole expression. Sub expression 1 will return “Bill Clinton” but for 4 characters only, the first sub expression “^(Bill|George|Renald)” is analyzed. Sub expression 2 will return “Clinton” for 7 characters, the second sub expression “(Clinton|Bush|Reagan)$” is analyzed.

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb
Written By Akki

Tutorial 36 - Regular Expressions in PPL

Regular Expressions (Regex):

From www.regular-expressions.info:

“A regular expression (regex or regexp for short) is a special text string for describing a search pattern. You can think of regular expressions as wildcards on steroids. You are probably familiar with wildcard notations such as *.txt to find all text files in a file manager. The regex equivalent is .*\.txt . But you can do much more with regular expressions. In a text editor like EditPad Pro or a specialized text processing tool like PowerGREP, you could use the regular expression \b[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]\b to search for an email address. Any email address, to be exact. A very similar regular expression (replace the first \b with ^ and the last one with $) can be used by a programmer to check if the user entered a properly formatted email address. In just one line of code, whether that code is written in Perl, PHP, Java, a .NET language or a multitude of other languages.”

PPL supports a variety of expressions like:

\Quote the next metacharacter
^ Match the beginning of the string
. Match any character
$ Match the end of the string
| Alternation
() Grouping (creates a capture)
[] Character class

==GREEDY CLOSURES==

* Match 0 or more times
+ Match 1 or more times
? Match 1 or 0 times
Match at least n times
Match at least n but not more than m times

==ESCAPE CHARACTERS==

\t tab (HT, TAB)
\n newline (LF, NL)
\r return (CR)
\f form feed (FF)

==PREDEFINED CLASSES==

\l lowercase next char
\u uppercase next char
\a letters
\A non letters
\w alphanimeric [0-9a-zA-Z]
\W non alphanimeric
\s space
\S non space
\d digits
\D non nondigits
\x exadecimal digits
\X non exadecimal digits
\c control charactrs
\C non control charactrs
\p punctation
\P non punctation

To search a string using regular expression in PPL you will use the Search() function. You can also make sure that the string is an exact match of the regular expression you are providing with the Match() function.

Let's take the following example:

string$ = "Bill Clinton";
expr$ = "^(Bill|George|Renald) (Clinton|Bush|Reagan)$";
Search(expr$, string$, b$, e$);
ShowMessage(b$ + "," + e$);

The expr$ variable contains an expression that says, if the first word is either Bill, George or Renald and that the string ends with Clinton, Bush or Reagan, we have a match. “Bill Clinton” will be the beginning of our result string, b$ and “” will be our ending string e$.

i$ = 0;
while(i$ <= subexpcount - 1)
subexp(string$, i$, begin$, len$);
ShowMessage("SubExp " + i$ + " = " + begin$ + "," + len$);
i$++;
end;

In the previous example, we check each sub expression to see what matched in the string string$ and where it started and how many characters the sub expression took from string$.
Sub expression 0 will return “Bill Clinton” for a length of 12 because it do the whole expression. Sub expression 1 will return “Bill Clinton” but for 4 characters only, the first sub expression “^(Bill|George|Renald)” is analyzed. Sub expression 2 will return “Clinton” for 7 characters, the second sub expression “(Clinton|Bush|Reagan)$” is analyzed.

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 35 - Structures in Linked-Lists

Written By Akki

Tutorial 35 - Structures in Linked-Lists

Structures in Linked-Lists

Linked-lists are very powerful and can allow for very complicated data storage. Now let's see how it possible to store a different structure type inside each list node.First we need to create our list node:

List(l$);
Add(l$);

We now have one list node in l$ and our current internal pointer is placed on that first node.

We can now define the variable type like we would with any other variable:

struct(l$, “a”, “b”);
l.a$ = 10;
l.b$ = 20;

We can now add a new node and store another structure into it:

Add(l$);
struct(l$, “c”, “d”);
l.c$ = 30;
l.d$ = 40;

Now let's iterate through the list and output the structure's element values:

ForEach(l$)
if (Lpos(l$) == 0)
ShowMessage(l.a$);
ShowMessage(l.b$);
else if (Lpos(l$) == 1)
ShowMessage(l.c$);
ShowMessage(l.d$);
end;
end;


The Lpos() function returns the current pointer position of the list always starting with 0.

Imagine the possibilities offered by such flexibility.

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 34 - Linked-lists

Written By Akki

Tutorial 34 - Linked-lists

Linked-Lists

Finally a chance to talk about the linked-lists. You have probably heard or learnt about them in school while studying C or maybe you've read about them on the internet or a magazine.

Here is a great explanation from the great wikipedia.com:

“In computer science, a linked list is one of the fundamental data structures used in computer programming. It consists of a sequence of nodes, each containing arbitrary data fields and one or two references ("links") pointing to the next and/or previous nodes. A linked list is a self-referential datatype because it contains a pointer or link to another data of the same type. Linked lists permit insertion and removal of nodes at any point in the list in constant time, but do not allow random access.”

In PPL linked-lists variables are extremely powerful and versatile. In each node you can have a different type of variable, structures or arrays. This opens up unlimited data storage in memory that is simply unmatched.

To create a list variable, there many ways, here is how you declare a list variable and how you add nodes to it:

List(l$);
Add(l$, 1, 2, 3, 4, 5);
Add(l$, “A”, “B”, “C”, “D”);


This new linked-list variable now contains 9 nodes with different values and types. Let's see how you can move through the nodes like other languages would allow you to:

First(l$);
while (1 == 1)
ShowMessage(l$);
if (Next(l$) == false)
break;
end;
end;

Here is how we iterate through the list in reverse order:

Last(l$);
while (1 == 1)
ShowMessage(l$);
if (Prev(l$) == false)
break;
end;
end;

The First() function moves the list internal pointer to the first node, Next() moves to the next node returning true if succeeded or false is past the end of the node list. The Last() function moves the internal list pointer to the last node in the list and the Prev() function moves to the previous node.

In PPL you can use the ForEach() statement to iterate through a list, an array, a structure or a matrix type variable:

ForEach(l$)
ShowMessage(l$);
end;

ForEachRev(l$)
ShowMessage(l$);
end;

If you need to store the list node value into another variable, you can place a second variable as a target in the ForEach() statement:

ForEach(l$, v$)
ShowMessage(v$);
end;

Let's see how PPL can access nodes at random order, PPL can access list's nodes just like regular arrays:

ShowMessage(l$[0]); // display 1
ShowMessage(l$[5]); // display A

How do we go to a specific node position? Simple, by using the Goto() function. How do we know what node is the current one? Use the Lpos() function. How many nodes are in the list? Use the Count() function.

Goto(l$, 0); // Like First()
ShowMessage(LPos(l$));
Goto(l$, Count(l$)-1); // Like Last()
ShowMessage(LPos(l$));

We can also move nodes around using the Lmove() function:

Lmove(l$, 3, 1); // This moves node 3 to node 1.

You can also insert nodes using the Ins() function:

Ins(l$, 0, 0); // Insert value 0 at node 0.

To delete a node from the list, you can use the Del() function, if you want to empty the whole list, just use Empty().

First(l$); // Move to first node.
Del(l$); // Deletes first node.
Goto(l$, 5); // Goto 5th node.
Del(l$); // Deletes 5th node.
Empty(l$); // Empty the whole list of all of its nodes.

In the next tutorial we will see how you can store different variable types like arrays and structures inside a list node.

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 33 - Creating dynamic PPL libraries.

Written By Akki

Tutorial 33 - Creating dynamic PPL libraries.

Creating dynamic PPL libraries.

PPL comes with some very powerful functions that looks very plain simple at first but when you start using them, only then can you understand their real power.

The Run() function does exactly what it is suppose to, it runs a PPL program. However you can run a program but keep it in memory to access its internal functions. To keep a program from being freed from memory after it is ran, you need to use the following as your main code.

func WinMain
// Initialization code
return (true); // keep the program in memory
end;


You must also note, that since PPL comes with a built-in linker, all unused functions will be removed from the compiled code in memory. You must then force the functions not to be removed by the linker using the forcelink statement.

forcelink func MyFunction (a$, b$)
// My function code
end;


Once all your functions, procedures and main code are all setup it is time to load the library in memory.

MyLib$ = Run(AppPath$ + "MyLibrary");

MyLib$ will contain the handle pointing to the compiled library. Notice that we didn't specify an extension to our file "MyLibrary". It is because PPL will detect if a .ppl or .ppc exists and use the right one. While developing your project leave the .ppl file there so that the code is recompiled as needed. When you distribute your program, just use the .ppc (compiled) file.

Now it is time to call one of the library's function.

result$ = Call(MyLib$, "MyFunction", 10, 20);

The Call() function is very powerful, it can accept as many parameters as are needed by the called function or procedure and can return a value. In our case here, we call the function named "MyFunction" inside the program pointed to by MyLib$, passing the values 10 and 20.

Once we are finished with the library, we can free it from memory using the KillApp() function. This will unload the program from memory.

KillApp(MyLib$);

Here is our library file MyLibrary.ppl:

forcelink func MyFunction(a$, b$)
return (a$ + b$);
end;

func WinMain
return (true);
end;


Here is our main program file Main.ppl:

proc main
MyLib$ = Run(AppPath$ + "MyLibrary");
ShowMessage(Call(MyLib$, "MyFunction", 10, 20)); // Should show 30
KillApp(MyLib$);
end;



How do we use variables between libraries?

The first and easiest way would be to use global variables with the % sign.

MyLibrary.ppl:

forcelink func MyFunction
return (GlobalVar1% + GlobalVar2%);
end;

func WinMain
return (true);
end;

Main.ppl:

proc main
GlobalVar1% = 10;
GlobalVar2% = 20;
MyLib$ = Run(AppPath$ + "MyLibrary");
ShowMessage(Call(MyLib$, "MyFunction")); // Should show 30
KillApp(MyLib$);
end;


The second way to do this would be to have a DownloadVars and UploadVars procedures to transfer variables from and to a library.

MyLibrary.ppl:

forcelink proc DownloadVars(v1$, v2$);
LibVar1$ = v1$;
LibVar2$ = v2$;
end;

forcelink proc UploadVars$(v$)
v$ = result$;
end;

forcelink proc MyFunction
result$ = LibVar1$ + LibVar2$;
end;

func WinMain
Global(Result$);
return (true);
end;


Main.ppl:

proc main
MyLib$ = Run(AppPath$ + "MyLibrary");
Call(MyLib$, "DownloadVars", 10, 20);
Call(MyLib$, "MyFunction");
Call(MyLib$, "UploadVars", &result$);
ShowMessage(result$); // Should show 30.
KillApp(MyLib$);
end;


We hope this tutorial will give you a good idea on how to split your program into dynamic modules that you can load and unload when needed.

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 32 - Multiple Windows

Written By Akki

Tutorial 32 - Multiple Windows

Using Multiple Windows (by Brad Manske)

I'd want to address issues dealing with the creation of multiple windows in your PPL programs. This is not a tutorial on creating windows. It is more a collection of tips for when you do create multiple windows. ShowMessage is the most simple way to create a second window. It is useful for debugging and simple informational pop-up windows.

ShowMessage("Hello World" + #13#10 + "and Country");

Take a look at the #13#10 added above. This is a Carriage Return/Line Feed added to produce a second line. By formatting the text, you can make this simple command very useful. The Windows MessageBox is the next step up in complexity. It allows you to set the owner, the text in the message box, the caption and some flags. In the example below, there is no owner, the question about saving, "Save" is placed into the caption bar, finally the "yes", "no" and "cancel" buttons are created inside the dialog box.

i$ = MessageBox(NULL, "Do you want to save " + FileName$ + "?", "Save", MB_YESNOCANCEL);

It is pretty obvious from the names below, which buttons get created when you use these constants.

MB_OK
MB_OKCANCEL
MB_ABORTRETRYIGNORE
MB_YESNOCANCEL
MB_YESNO
MB_RETRYCANCEL

You can also specify an Icon to be placed in the MessageBox from the list below. Simply use the "|" OR operator.

For example MB_YESNOCANCEL | MB_ICONQUESTION

MB_ICONHAND
MB_ICONQUESTION
MB_ICONEXCLAMATION
MB_ICONASTERISK
MB_ICONWARNING = MB_ICONEXCLAMATION
MB_ICONERROR = MB_ICONHAND
MB_ICONINFORMATION = MB_ICONASTERISK
MB_ICONSTOP = MB_ICONHAND

MessageBox has additional features. Refer to MSDN for all of them. MessageBox can return a value based when the button is pressed. These values are defined in Dialog.PPL.

#define IDOK 1
#define IDCANCEL 2
#define IDABORT 3
#define IDRETRY 4
#define IDIGNORE 5
#define IDYES 6
#define IDNO 7

I try to use these values when returning from displaying a dialog box. When using ShowModal to display a dialog any value less than 100 can be use for a button and it will return automatically, I try to avoid confusion and not change the meaning of the defined values. Going back to my MessageBox example from above, "Yes" and "No" are pretty clear answers, but what about "Cancel"? If you are asking to save the file in response to a command to exit the program, the program flow go like this. User selects the Exit menu item. The menu exit handler would send a
WM_CLOSE command. Then you need a handler for the close event. In the Close event handler, call the MessageBox function and if you receive the "Cancel" ID, then return a FALSE from the OnClose event to stop the program from closing. The operation of the OnClose event is a little different in windows than it is in PPL. Windows will only send you an OnClose event when the entire application is closing. PPL allows you to open multiple windows per application and will send you an OnClose event for each window. This makes it easy in PPL to implement the ability to "Cancel" for each window. The next step is having more than one fully functional window for your application. For each new window that you create with the Form Editor, you need to:

• Select the Generate Library option in the Form -> Options menu.
• Change the form name so that a new windows class is created.
• Give each control on the forms a unique name.
• Give each control on the forms a unique ID. (required if getting the handles from the IDs)

For most forms you will probably want to select the "FormDefault" property. This property enables the use of the SIP (Soft Input Panel) on the PPC. You may open several windows for your program at the same time, then manage input by selectively showing the window that is needed. To Hide or Show a window use:

ShowWindow(FormHandle$, SW_HIDE); // or SW_SHOW

In creating more complex windows, you need to be careful about which styles are selected. The example below is how I added styles in the creation code for a window. This was necessary because the WS_EX_CaptionOKBtn style prevented my window from displaying on the PC as it is a PPC only style. So if your window refuses to display at all, you should review the styles that you have used and isolate the trouble-maker.

ExStyles$ = GetWindowLong(SizeDlgHandle$, GWL_EXSTYLE);
#ifdef _WIN32_WCE
// WS_EX_CAPTIONOKBTN is added here and not on the form because if added to
// the form then the form will not display on the PC
SetWindowLong(SizeDlgHandle$, GWL_EXSTYLE, ExStyles$ | WS_EX_CAPTIONOKBTN);
#else
// WS_EX_TOOLWINDOW is added here for the same reason as above except it will
// not show on the PPC if present.
SetWindowLong(SizeDlgHandle$, GWL_EXSTYLE, ExStyles$ | WS_EX_TOOLWINDOW);
#endif

I hope that this collection of tips has helped.

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 31 - Packages

Written By Akki

Tutorial 31 - Packages

Packages Come In All Sizes (by Eric Pankoke)

There will be very few instances where you will need to distribute an application without some sort of supporting file set. Whether you’re building a database system or a multimedia application, you might have one or more directories filled with extra material that you don’t necessarily want the user to see outside of the application itself. PPL provides a nice mechanism for this through the use of a Package file. A package file is a file that can contain one or more files of any type all bundled up together into one file with a .pkg extension. You can create a package file pro grammatically or you can use the Package Manager supplied with PPL to do so. Run the PPL console (it’s called PPL.EXE, and resides under the RUNTIME directory of your PPL install). From the File menu, select Package Manger. You can use this tool to view, create and manage package files. It’s pretty self explanatory, so I won’t really go into details here. Once you’ve created a package file, you’ll of course want to use it in your program. To open a package
file, you simply call:

handle$ = OpenPackage(AppPath$ + “mydata.pkg”, key$);

The first parameter is a full path and name to the file you wish to open, and the second parameter is the key used to unlock the package file. If a file with the name you’ve specified does not exist, OpenPackage will create it and use the value specified in key$ as the password. When creating a package file in the Package Manager you do not get the opportunity to supply a key, so key$ would be an empty string (“”). If you want a key, you will need to create the package pragmatically. You must be sure to keep track of the return value, as this is the handle that will be passed to all other package functions.

To retrieve the contents of a package file, call:

PackageFiles(&lst$, handle$);

This will provide you with a list containing the names of all of the files contained in the package. Of course, you will probably know all of these names already, so let’s get to the heart of the matter: extracting and using the files. There are currently two ways of retrieving a file. The quickest way is to call the following:

data$ = LoadPackageFile(handle$, “filename”);

This returns the contents of the file as a string in memory, which you can then display or manipulate however you choose. Currently, if the file is some sort of multimedia file or a database, this won’t be of much use to you. Starting in PPL v1.1, however, there are two new functions that will work in conjunction with LoadPackageFile called LoadSpriteFromMem and LoadSoundFromMem. These will be discussed more after 1.1 is released. For cases where you need to interact with the file in some way, you’ll want to call:

tmpfile$ = ExtractFileFromPackage(handle$, “filename”);

This function will retrieve the contents of the requested file and store it in a temporary file. The return value is the name of the temporary file where the data is stored. So let’s say you wanted to retrieve a database, do some work on it, then store the database back to the package. The code would look something like this:

dbfile$ = ExtractFileFromPackage(handle$, “MyData.db”);
dbhandle$ = sql_open(dbfile$);
if(dbhandle$ > 0)
//Check out the October newsletter for an SQLite primer
end;
dbnew$ = ExtractFilePath(dbfile$) % "aviator.db";
MoveFile(dbfile$, dbnew$);
AddFileToPackage(package$, dbnew$);
DeleteFile(dbnew$);

If you will need to place the file back into the package after you’ve done your work with it, the 3 lines following end; are necessary. ExtractFileFromPackage creates a random name for the file, and AddFileToPackage takes the name of the file you’re adding and uses that as the name inside of the package. So, if you want to replace the file that exists in the package with the version your application has just modified, you need to rename it to match the name that exists in the package. ExtractFilePath returns the path portion of a path / file name string, so if you use that on the file path returned from ExtractFileFromPackage, then use the file name that was used to add the file to the package initially, you can rename the temp file so that it will be stored correctly in the package again. The final step to updating the package is:

AddFileToPackage(handle$, “filename”);

The first parameter is that wonderful handle that was retrieved on your call to OpenPackage. filename is a string containing the full path and name of the file you wish to add. As mentioned before, the actual name of the file (no path) will be used to reference the file within the package. If you call AddFileToPackage with a file that already exists in the package, the file in the package will be replaced with the one you are adding. Finally, when all of your work is done and you don’t need the package any more, simply call:

ClosePackage(handle$);

This will make sure that the contents of the package have been updated and the handle will be released from memory.

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 30 - Arrays in Structures

Written By Akki

Tutorial 30 - Arrays in Structures

Arrays in structures.

We have seen that structures can be defined as arrays using the TDIM() function. But what about having one element of the structure being an array of values? PPL offers a transparent way to do just this using the DIM() function. It will create an array from Lets first start by defining our variable structure:

struct(s$, "a", "b");

Now lets dimension our element, in our case we will use s.a$:

dim(s.a$, 10);
s.a$[0] = 1;
s.a$[1] = 2;
s.b$ = 3;
ShowMessage(s.a$[0] % "," % s.a$[1] % "," % s.b$);

You can even use strings with your array element, don't forget to use the @ operator to convert array elements to string since they only point to a pointer:

s.a$[2] = "Hello World!";
ShowMessage(@s.a$[2]);

As you see, structures are very flexible and quite efficient too. They can support multiple type of data, even arrays of double type values and even strings.

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 29 - Arrays of Structures

Written By Akki

Tutorial 29 - Arrays of Structures

Arrays of structures.

There comes a time when you need to store a series of data in the same format. Storing values in a structure will help clarify your code and your programming task as well. However, you might want to store more of the same data in multiple structures. This is where arrays of structures become very handy.

Lets first define our structure variable format:

struct(s$, "a", "b");

Next we will make this structure an array but keeping the structure information at the same time. Notice we use TDIM() and not the regular DIM() function? The TDIM() function is a special function that can be used with structures only.

tdim(s$, 10);
s.a$[0] = 1;
s.a$[1] = 2;
ShowMessage(s.a$[0] % "," % s.a$[1]);

Arrays of structures are very ressemblant to lists of structures but offers an a great alternative is lists are too complicated for you.

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 28 - List of Structures

Written By Akki

Tutorial 28 - List of Structures

List of structures.

Now that we know about structures, how can we store multiple structures into one single variable? The best solution is either:

1. An array of structures
2. List of structures.

Let's take a look at list of structures and later array of structures. Everytime you add a new item to a linked-list, the variable type is initialized, therefore you need to restructure the item.

For (i$, 1, 10)
Add(l$);
struct(l$, "a", "b");
l.a$ = i$;
l.b$ = i$ + 10;
end;

ForEach(l$)
ShowMessage(l.a$ % "," % l.b$);
end;

There is nothing more to add here other than the fact that you can define different types of structures for each list item. Powerful isn't it?

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 27 - Structures 2

Written By Akki

Tutorial 27 - Structures 2

Structures revisited!

Structures offers enormous flexibility when you design a program. They allow to store information in a nice clean way into your variables. I like to explain structures as a single record database. A structure is like a series of fields that can be stored in one record (the variable). Take the following example:

struct (s$, "a", "b");

The variable s$ has two elements, a and b. Each element can contain a separate value. The default type for structure's elements is a TINT (4 bytes) value. You can also specify which value type the element will be holding.You have multiple choices here:

TBYTE 1 byte
TSHORT 2 bytes
TINT 4 bytes
TUINT 4 bytes (unsigned)
TWIDE 4 bytes (unicode character string)
TDOUBLE 8 bytes
TLONG 8 bytes (no decimal)

struct (s$, "a", tbyte, "b", tdouble);

The following structure s$ would be 9 bytes in size. 1 byte for element a and 8 bytes for element b. If you need to specify your own size in bytes you can also easily do it:

struct (s$, "a", tbyte, "b", 50);

Element b contains 50 bytes. Now how do you access the structure variable elements you ask? Noting is easier:

s.a$ = 10;
s.b$ = 20;

What about strings in structures? You will see that PPL is very flexible but can also be a little more complex to use in some cases. You will need to be careful when using strings in structures. PPL either stores a pointer of the string that is assigned to the structure's element in the case where the element size is TINT, TUINT, TWIDE, TDOUBLE or TLONG. If the element size is a user-defined length, then the string is copied directly to the structure's element memory location.

struct (s$, "a", "b", 50);
s.a$ = "Hello World!";
s.b$ = "Hello Again!";

The main difference here is that the string "Hello World!" is not stored in s.a$ but rather stored somewhere in memory and only its pointer address is stored in s.a$. "Hello Again!" is stored directly into s.b$.

ShowMessage(s.a$);

If we try to access s.a$ like the previous code, only its pointer address value will be printed. To access s.a$ as a string we need to use the @ operator to convert a pointer to a string.

ShowMessage(@s.a$);

Now "Hello World!" will be printed in the dialog message. To access s.b$ no need to do anything special.

ShowMessage(s.b$);

This will display "Hello Again!".

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 26- Arrays

Written By Akki

Tutorial 26- Arrays

Introducing Arrays.

When it comes time to store multiple values into a single variable, we have two choices:

1. Use an array variable
2. Use a linked-list variable

We will use the array variable for now since we will review the linked-list variable type in a later tutorial. PPL offers many ways to work with array variables, including arrays of different sizes and arrays of strings.

Arrays can be defined on local or global variables. To define an array, PPL comes with multiple functions to help you do this.

Dim(var$, 10);

This will create an array of 10 elements of the default type TDOUBLE (8 bytes) for variable var$. To declare multi-dimensional arrays, do the following:

Dim(var$, 10, 10, 10);

You can later access arrays just like other variables by specifying an offset within brakets [].

Dim(var$, 10, 10);
var$[0, 0] = 102.24;
var$[9, 9] = 23.2873;

Notice that we use 0,0. Arrays offsets start at 0 and goes to the array size – 1. If your array size is 10, 10, then the minimum offset if 0,0 and the maximum offset is 9,9. To create arrays with custom element sizes, use SDIM().

SDIM(var$, TBYTE, 10, 10);

This will create an array of 10, 10 elements of type TBYTE (1 byte).

Now, what about strings? You will be happy to hear that PPL handles strings transparently with just a little twist. PPL stores only the string pointer address in the array's elements. Therefore the use of the @ operator is required to retrieve the string when accessing an array element.

Dim(var$, 10);
var$[2] = "Jack Bower";
var$[3] = "Joe Bloe";
ShowMessage(@var$[2] % " " % @var$[3]);

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 25 - Screen origin

Written By Akki

Tutorial 25 - Screen origin

What are your origins?

The screen display can be moved around. The starting origins are at coordinates (0, 0). You can move the screen in any direction. All the sprites will move according to the screen origins. You can design maps with lots of sprites on them, then scroll the whole map just changing the origin values.

SetOriginX(10);
SetOriginY(-10);

If you need sprites such as interface icons to remain at certain physical screen coordinates (always visible), rather than coordinates that are relative to the origin, you will need to add the following options to the sprites:

SO_FIXED, SO_FIXEDX or SO_FIXEDY.

SO_FIXED will keep the sprite at the pixels they are assigned to, even if the origins of the screen are changed. SO_FIXEDX will keep the X axis of the sprite fixed while the SO_FIXEDY will keep the Y axis location of the sprite fixed.

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 24 - Sprites

Written By Akki

Tutorial 24 - Sprites

Refresh your game with a sprite!

Now is the time to spice up your game knowledge and get into something really cool: Sprites. Remember the old days of the Nintendo (NES) or the Super Nintendo (SNES) video game consoles? Most games you played back then were using sprites. Sprites are basically just an image you can move around and animate. In PPL sprites are pretty advanced. You can stretch them, tint them, tile them, automatically animate them, and so much more...

Let’s first start by loading an image from disk as a sprite:

MySprite$ = LoadSprite(AppPath$ + "mysprite.bmp", G_RGB(255, 0, 255), 4, 150, NULL);

You always need to retrieve the sprite handle from the LoadSprite() function to be able to access it later on. The sprite handle is just a unique integer value.

The first parameter of the LoadSprite() function is the pathname of the image you wish to use. The image file can be a bitmap (.bmp), a jpeg (.jpg), a Portable Image (.png) or a gif (.gif). The image file can be made of multiple images grouped together in one image file.

The second parameter is the transparent color to use. Sprites can be drawn on the screen with a transparent background to make them blend with the scenery.

The third parameter is the number of frames (images) the image file has. The images must be sequential (one after the other) horizontally within the file, and they all must be the same width and height in pixels.

The fourth parameter is the speed in milliseconds at which the animation will be played. The default animation will swap between each frame one after the other from the left to the right.

The last parameter is the sprite procedure to use for the sprite. We will get into more advanced sprite handling in a later article.

The image is by default visible on the screen at position (0, 0). You can hide or show the sprite using the following:

DelSpriteOption(MySprite$, SO_VISIBLE); // Hide the sprite by removing the SO_VISIBLE flag from the sprite's options.
AddSpriteOption(MySprite$, SO_VISIBLE); // Show the sprite by adding the SO_VISIBLE flag to the sprite's options.

Each sprite has a series of special options that can be removed or added at any time.

Now let's move our sprite on the screen, to move the sprite all you need to do is call the MoveSprite() function and pass a new coordinate. In our case we will move the sprite to where the stylus touches the screen.

In the MainProc of our code we will add a WM_LBUTTONDOWN event that will be triggered whenever the stylus touches the screen:

WM_LBUTTONDOWN:
MoveSprite (MySprite$, wParam$ - (SpriteWidth(MySprite$) / 2), lParam$ - (SpriteHeight(MySprite$) / 2));

Here we center the sprite MySprite$ - which we should have made global at the time of loading (LoadSprite) - around the stylus position. SpriteWidth() returns the width in pixels of the sprite and SpriteHeight() return its height in pixels.

The WM_LBUTTONDOWN uses the wParam$ variable to store the X coordinate position and the lParam$ variable for the Y coordinate position the stylus was pointing to. You can write code for the following events:

WM_LBUTTONDOWN: The stylus is pressed.
WM_LBUTTONUP: The stylus is released from the screen.
WM_MOUSEMOVE: The stylus is being moved around while pressed.

You can stretch a sprite's display by doing the following:

SetSpriteWidth (MySprite$, 100); // Makes the sprite 100 pixels wide.
SetSpriteHeight (MySprite$, 200); // Makes the sprite 200 pixels high.

You can change the animation speed and sequence of a sprite, lets say you have frames for jumping at frame 6 to 10:

SetSpriteFrames (MySprite$, 6, 10, 250, true);

This will set the current animation for MySprite$ from frames 6 to 10, animating at 250 milliseconds. The last parameter specifies if PPL should wait for the current animation timer to expire before going to the new animation frames or change right away.

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 23 - GameAPI 2

Written By Akki

Tutorial 23 - GameAPI 2

Draw me a picture I don't get it!

The GameAPI screen is represented by a series of pixels organized on an x and y axis. Position (0, 0) is the top left of the screen and (240, 320) is the bottom right for the typical QVGA display on a PocketPC and (480, 640) is the bottom right for a typical VGA display device.

Drawing to the screen is very simple with the GameAPI, you just need to know where to place the drawing code. Since the first part of our series of articles on the GameAPI talked about a basic code template to create a GameAPI program, we need to focus a little more on the WM_PAINT event here. The WM_PAINT event is called every frame the GameAPI needs to draw to the screen. The WM_PAINT is placed in the game procedure code, like this:

func GameProc(hWnd$, Msg$, wParam$, lParam$)
case (Msg$)
WM_PAINT:
G_Clear(0);
end;
end;

When you initialize the GameAPI you pass the GameProc pointer to the InitGameApiEx() function. PPL will then use this function to trigger custom events like WM_PAINT, WM_TIMER and WM_COLLIDE.

InitGameAPIEx(h$, &GameProc, 240, 320, false, 5, 60);

Inside the WM_PAINT code you can put any type of drawing code you want, like g_clear(0) to clear the screen with a color you like, g_textout() to draw informative text and g_fillrect() to draw a rectangle. PPL comes loaded with a ton of drawing functions. PPL clears the screen in black by default if no WM_PAINT event is defined.

What if you want to draw something on the screen outside the WM_PAINT event code? It’s easy, but you need to follow some guidelines. You need to prepare the screen to be drawn to and when done you need to update the screen. Here is simple code to draw a rectangle, wait 5 seconds and then return to normal drawing of the screen either by triggering the WM_PAINT code or by simply clearing the screen with black.

g_beginscene;
g_fillrect(10, 10, 100, 100, g_rgb(100, 100, 100));
g_update;
delay(5000);

Be careful not to call g_beginscene() without calling a corresponding g_update(). Follow this rule and you will never have any problems.

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 22 - Launch programs

Written By Akki

Tutorial 22 - Launch programs

How to launch an executable from PPL (by Eric Pankoke)

For any number of reasons, you might want to launch an external program from your PPL application. It’s actually rather simple to do. First of all, if you’re not writing a GUI application, you need to include the following file:

#include "windows.ppl"

If you want to launch a program and have it open normally, here’s a quick function to do so:

proc LaunchProgram(path$)
#ifdef _WIN32_WCE
path$ = wide(path$);
verb$ = wide("open");
#else
verb$ = "open";
#endif

struct(info$, SHELLEXECUTEINFO);

info.cbSize$ = sizeof(info$);
info.lpFile$ = &path$;
info.nShow$ = SW_SHOWNORMAL;
info.fMask$ = SEE_MASK_NOCLOSEPROCESS;
info.lpVerb$ = &verb$;
result$ = ShellExecuteEx(&info$);
end;

For more details on how this works, look up the ShellExecuteEx() function on MSDN. To launch an application, you use “open” for the lpVerb member of the SHELLEXECUTEINFO structure. Other supported verbs are dependent on the program that you are attempting to launch, and it will be up to you to figure those out. Path$ should be a fully qualified path / file name combination. Below is a quick demonstration that you can use in a non-GUI application to see how this works:

func WinMain()
#ifdef _WIN32_WCE
LaunchProgram(GetWinDir() + "addrbook.exe");
#else
LaunchProgram(GetWinDir() + "
\\notepad.exe");
#endif

return(false);
end;

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 21 - The Console

Written By Akki

Tutorial 21 - The Console

The PPL Console (by Brad Manske)

A Console Program is a text only interface. It is still a windows program but it eschews the Graphical User Interface (GUI) and event oriented programming for the sake of simplicity. This is just the kind of program you want if your program just processes data and return results. In most cases, when testing the compiler it is quicker and simpler to use the PPL console than to write a Windows GUI program.

To see an example of a console program open the "PPL IDE" link in the PPL program group. Then select "Console..." from the file menu. The PPL console will evaluate what you type on the input line at the bottom and display the results in the output window.

Typing:

10+10

for example, will display 20

It will also work with variables. Try this example:

a$=10
b$=20
a$+b$

The output window will display

> a$=10
10
> b$=20
20
> a$+b$
30

The expressions that PPL can evaluate can be quite complex in this mode and it makes for a handy tool. The real value in the console is using it in your own code. "Hello World" looks like this for a console program:

#include "console.ppl"
func WinMain
InitConsole;
ShowConsole;

write("Hello World");

return (true);
end;

Notice that this is a windows program, so it begins with WinMain. The Console is created and then made visible on the screen. The Write() statement sends the string to the console to be displayed. A Writeln() command also exists that will start a new line after the string has printed. The program ends by returning "true" so that the Console window stays open until the user closes it.

All that remains is to add your code in place of the write statement and you have a way to do unit testing on small pieces of your code. Here are a few string handling operations to get you going:

Write - Send a string to the console
Writeln - Send a string to the console then start a new line
+ - Concatenate 2 strings if alphanumeric ("ab"+"12"="ab12")
+ - add the value of 2 strings if numeric ("10"+"10"="20")
% - Concatenate 2 strings ("ab"+"12"="ab12" or "10"+"10"="1010")
"\n" - advance to the next line on the console

If you want even more control over how the console displays your data, then consult the manual for the "sprintf" statement. C language programmers will recognize this powerful formatting statement. For example:

MyValue$ = 1234;
sprintf(tmpString$, "Value printed in an 8 char field %8d", MyValue$);
write(tmpString$); // " 1234"

If you've followed along so far, you get rewarded with the best tip for using the console, which I have saved for last. ShowMessage() is often used to show the state of the program at some point to help with debugging. But sometimes it doesn't work or you spend all day clicking "OK" because you have to go through a large amount of data before you get to the point in the data where it doesn't work. Instead of dealing with all of that hassle, use the Console.

Create your window, and after the User Interface has been created add InitConsole() & ShowConsole(). Write out the debug statements and before exiting save the console to a file. Now you can search for the case you’re interested in with a text editor.

You should enclose all of the Console calls in #ifdef statements so that they can easily be removed for a production build.

#undefine ProductionBuild // change to #define for no console

#ifndef ProductionBuild
#include "console.ppl"
#endif

func WinProc

// your code - create UI or call the form creation.

#ifndef ProductionBuild
InitConsole;
ShowConsole;
#endif

// your code

#ifndef ProductionBuild
Writeln("Show interesting data in your code.");
#endif

return(true);
end;

That is the quick run down on the console. I've never tried using the Console to log the progress inside a game. I'm hoping that some game designer out there will give this a try. If you do, please tell us all about it in the Forums at http://www.arianesoft.ca/forum.php.

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 20 - Structures

Written By Akki

Tutorial 20 - Structures

Put some structure in your life!

Life can be a real succession of disorder sometimes. Don't let this way of life turn your programs into nightmares. Put some structure into your code. Variables are a great way to organize and store information, but you need to classify this information into clean and organized structures to be able to keep your code expandable for the future.

A typical variable can be declared and accessed quite easily in PPL. You declare its scope (local or global) if wanted and then you assign values into it. Nothing new here. What if you have a whole lot of information you want to store into variables? Are you going to create one variable for each value you need to store? If you have answered yes to this question, you need to read further as you will discover that structured variables will give you benefits you probably never considered.

Let’s pretend we need to write a simple three questions survey program. We need to gather user information first and then the user’s answers to three questions. You could do the following:

Name$ = "Alain Deschenes";
Address$ = "Somewhere somehow";
Tel$ = "555-555-5555";
Age$ = "32";
Occupation$ = "Too busy";

Question1$ = "His answer #1";
Question2$ = "His answer #2";
Question3$ = "His answer #3";

This will probably turn into a real nightmare when you reach 500 lines of code or more. What if you spell a variable wrong? What if you need to add user information and questions?

With structured variables (called structures), you can group a series of variables into what you might call categories. In our scenario here, we would need a user$ structure and a questions$ structure. Each structure will hold a series of variables.

struct(user$, "Name", "Address", "Tel", "Age", "Occupation");
struct(questions$, "Question1", "Question2", "Question3");

User.Name$ = "Alain Deschenes";
User.Address$ = "Somewhere somehow";
User.Tel$ = "555-555-5555";
User.Age$ = "32";
User.Occupation$ = "Too busy";

Questions.Question1$ = "His answer #1";
Questions.Question2$ = "His answer #2";
Questions.Question3$ = "His answer #3";

Yes it is longer to write but if you use this technique you are guaranteed to get great benefits in the long run.

You can declare as many structure elements as you want inside the Struct() function. Each element you declare is by default a double type variable that can hold pretty much any numerical value. However you can change the type of element you need. There are multiple variable types that PPL can support including:

TBYTE : 1 byte value. Range from 0 to 255.
TSHORT : 2 bytes value. Range from 0 to 65535.
TINT : 4 bytes value.
TUINT : 4 bytes unsigned value.
TDOUBLE : 8 bytes value. Support decimal point.

You can create a structure that will hold 4 bytes with 4 elements of 1 byte each.

struct(mystruct$, "a", tbyte, "b", tbyte, "c", tbyte, "d", tbyte);
mystruct.a$ = 1;
mystruct.b$ = 2;
mystruct.c$ = 3;
mystruct.d$ = 4;

You can also define a custom number of bytes the element will hold. You can then access each byte of the element variable using [x] array syntax.

struct(mystruct$, "element", 256);
mystruct.element$[34] = 20;

You can also copy one structure to another variable by doing the following:

newstruct$ = mystruct$;

You can also pass structures as parameters of funcs or procs like this:

proc MyProc (s$)
s.a$ = 10;
s.b$ = 20;
s.c$ = 30;
end;

proc main
struct(mystruct$, "a", "b", "c");
MyProc (&mystruct$);
ShowMessage(mystruct.a$ + ", " + mystruct.b$ + ", " + mystruct.c$);
end;

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 19 - Keep your code separate

Written By Akki

Tutorial 19 - Keep your code separate

Keep your code separate by Richard Gamester

Following on from All About Forms, I would like to tell you about keeping your code safe.
No, not backup's - that should be normal practice, but the best way to control your ever expanding code, but first we need to understand this bit of the PPL window:

Project.gif


This is your friend the Project Manager, this is where you can list all the parts of your project. As before, I will be using my Test project, in the folder Test. The first thing you need to do is add your form. Click the green plus icon and open the Test.frm file. Do not be tempted to add the Test.ppl file of the same name, it will only confuse you later. This file is the one auto-generated by PPL.

The Project Manager is the quickest way to open your form (frm) or code file (ppl) if you close them in the main window. To be safe, you should place all your main-line code in additional .ppl files.
Doing this is quite simple:

Click File > New

You now have a blank form to put your code in! But I suggest you do the housekeeping first and..

Click File > Save

Save your new file and call it something meaningful like Test2.ppl, save it in the project folder with the Test.frm file, then add it to the project list in the same way as you loaded the form.

The next thing to do is tell PPL about your file.

This is quite simple, just add a statement like this to the Form > Initalization Section Code area..

#include "Test2.ppl"

You can then cut and paste your code as procedures or functions in the new file

Here is one last thought. If your routine Test2.ppl relies on several sub routines, these can be put in Test3.ppl.

But this time put the #include for it at the top of the Test2.ppl file.

This has the advantage that your sub-routines are defined before the calling code, so you will not need to use forward statements.

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 18 - All about forms

Written By Akki

Tutorial 18 - All about forms

All About Forms by Richard Gamester

By now you have had a play with PPL., tried creating a form, maybe even started to write a program!
So now is the time to learn a bit more about forms and how the compiler keeps track of all your code!

Start PPL and click Project > New

In the new project window. select Blank Project, then type a different name where it says project name. In this document I will use "Test" but the choice is yours. Click the Ok button.

PPL will create a new folder of that name in your project folder.

Click Tools > Visual Editor

A new form will then be created and displayed in the window.


Click an item in the "controls" tool bar, lets say a button (OK).

Tool.gif

Now it is time to save your form, click File > Save and save the file in your new folder as Test.frm.

Double click your button. PPL will create a procedure for the (default) OnClick event
Type in a ShowMessage command like this:

ShowMsg.gif

Right click the #button101 tab and select close. When asked, say Yes to save it.

With the form showing, click the Form > Initalization Section Code

Form.gif

In the new window type a comment like

// Initalization code here!

Right click on the #%init tab and select close, when asked say yes to save.

Now click Form > Form Creation Code

In the new window type a comment like

// Form code in here!

Right click on the #%create tab and select close, when asked say yes to save.

Let's see the result

Click Form > Create Source

What you see now is the PPL file generated from your work so far. On about line 10 you will see your comment:

// Initalization code here!

This is where you would put the #include statements for other PPL files that you needed in your project.

Following this are the button events (the close menu item is created for you) and the one in which you typed the ShowMessage. In fact, the events for all your controls will be in this area.

Then we get into the form creation code, it starts:

func WinMain

This is where PPL writes all the code required to create your form. Right down at the bottom, you will see:

#code
// Form code in here!
return (true);
end;

You will see that the "form creation code" is just an extension of the PPL generated WinMain function code. The return (true) is added by PPL.

Note that what you are seeing is code generated by PPL. Do NOT try to edit this as your changes will be lost!

PPL keeps the all the events for initialization, form creation and form components separate. This makes it far easier for the user (honest)! It also allows PPL to remove the code if you delete the component.

If you want to edit the form sections you have to return to the form and use the Form menu. For control events double click the control or use the events menu.

Lines like this

#code

are just commands to the compiler to include your text from the Test.frm file.

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 17 - Handling double-clicks in PPL

Written By Akki

Tutorial 17 - Handling double-clicks in PPL

Handling double-clicks in PPL

Windows doesn't simplify the task of handling double-clicks. It makes hard for us. Here is a piece of code to simplify your life a little.#declare GetDoubleClickTime apidll GetDoubleClickTime 0 1

#declare GetDoubleClickTime apidll GetDoubleClickTime 0 1

func mainproc(hWnd$, Msg$, wParam$, lParam$)
// Make ClickCount$ global
global(ClickCount$);

ok$ = true;

case (Msg$)

WM_CLOSE: // Window is closed
ShutGameAPI(hWnd$);

WM_LBUTTONDOWN: // Stylus is pressed.
// Get double click time set in milliseconds in Windows.
t$ = GetDoubleClickTime;

// Add 1 to our clickcount variable.
ClickCount$++;

// Loop for double-click time processing windows messages.
lasttime$ = tick;
while (tick - lasttime$ < t$)
HandleMessage;
end;

// If only one click is used it is a single-click.
if (ClickCount$ == 1)
g_ShowMessage("Single-click");
ClickCount$ = 0;
else
g_ShowMessage("Double-click");
ClickCount$ = 0;
end;

WM_KEYDOWN: // A hardware key or software key is pressed.
PostMessage(hWnd$, WM_CLOSE, 0, 0);

end;

return (ok$);

end;

You can apply this to sprite functions as well on the WM_LBUTTONDOWN event.

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 16 - Getting a list of all files in a folder

Written By Akki

Tutorial 16 - Getting a list of all files in a folder

How do I get the list of files in a folder?

You need to extract all the possible information from a folder but don't know where to start? Look no further, PPL offers a great flexibility when it comes to using Windows API functions.

The following code will open up the console and output all the files that are contained in the C:\Program Files\PPL\Runtime\ folder.

A new list item is created to store all the filenames.

Imagine the possibilities... The fd$ structure contains important information about each file scanned, like: File attributes, Creation Time, Last Access Time, Last Write Time, File Size and Filename.

#include "console"
func WinMain
InitConsole;
ShowConsole;

List(files$);
  struct(fd$, WIN32_FIND_DATA);
i$ = FindFirstFile("c:\\Program Files\\PPL\\*.*", &fd$);
if (i$ != INVALID_HANDLE_VALUE)
repeat
Add(files$, char(fd.cFilename$));
until (FindNextFile(i$, &fd$) == false);
FindClose(i$);
end;

ForEach(Files$);
Writeln(Files$);
end;

return (true);
end;

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 15 - Installing PPL manually

Written By Akki

Tutorial 15 - Installing PPL manually

Installing PPL manually on your PDA / Smartphone

The beauty of PPL is that it can run on most StrongARM or XScale powered devices running under PocketPC 2000, 2002, Windows Mobile 2003, 2003se and 2005. However the installer can give you a hard time if your device is not recognized.

There is a solution for you. Install PPL manually. Sounds complicated? Not at all. Here are the steps you will need to follow.

1. Install the latest version of PPL on your desktop PC.

2. Copy the files inside the RUNTIME folder over to your phone using ActiveSync. Copy all the files inside C:\Program Files\PPL\Runtime\*.* to \Program Files\PPL\.

3. Copy PPL.EXE from your PC at the location: C:\Program Files\PPL\PPC\WM2003\PPL.EXE to your phone at \Program Files\PPL\PPL.EXE

4. Now copy \Program Files\PPL\PPC\WM2005\gsgetfile.dll to \ProgramFiles\PPL\gsgetfile.dll

5. On your phone, go into the File Manager application and run \Program Files\PPL\PPL.EXE. The device might ask questions about whether to trust this application, answer yes. It will come up eventually and setup. When done, exit the application.

6. On your PC, start up the PIDE application. At the far right, there is a dropdown box for the target, set the target to Target->Pocket PC.

7. Now compile and run. Again, the first time (or few times) you do this, the device might complain about untrusted applications, continue to answer yes to running them. After answering yes you will see your application run.

If you want to make a standalone application that runs on your device, go to the menus in PIDE, and select
Run / Make Executable. This will make an executable of your project file into the \My Documents directory on your device. The first time you run it, you'll get the untrusted application message, but after that it will just run.

NOTE: The IDE does not run properly on the Motorola Q at this moment due to the screen size, in the meantime you can use the PIDE on your desktop.

Thanks to Rick Eesley for his instructions and patience!

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 14 - Distributing your PPL application.

Written By Akki

Tutorial 14 - Distributing your PPL application.

Distributing your PPL applications.

You are now done testing and debugging your application. It is time to distribute it to your clients or sell it. PPL offers a multitude of ways to do this.

The first method of distribution is to create an executable file (.exe), pack all your files in a zip file and send it over. The second method is to distribute the PPL compiled file (.ppc) file. It is a compressed and encrypted bytecode version of your source code. If you do this you will need to distribute the PPL.EXE application that you can rename to your liking ex: MyApp.exe. You will now need to rename the MyApp.ppc file to Autorun.ppc. PPL looks for Autorun.ppl or Autorun.ppc file at launch time.

Let's review each method one by one:

Create an executable.

There are two ways to generate an executable file in PPL. First you need Pro version to do this. You can use the PIDE by selecting Run / Make Executable. You have a couple choices here:

1. Type of executable you want to generate.

Desktop PC executable.
PocketPC 2000, 2002 compatible executable.
Windows Mobile 2003, 2003se and 2005 compatible executable.

2. Icon file. Allow you to select an icon for your executable file.

3. Use compressed library. This will use the compressed libraries to build your executable. Compressed libraries are about 3 times smaller than normal library files but they can be a little slower to load on some machines.

The second way is to use the main PPL interface on the PocketPC. Here the options you can set:

1. Root file. This is the PPL file to create an executable with.

2. Exe type. Select the executable format to generate. These are the same settings as on the PIDE above.

3. Compressed runtimes. Same as the PIDE.

Once your executable is created you will need to include the external support files that will be used by your application. That is bitmap image files, sound files, text files, data files, etc... It is good practice to keep all files within the same folder or in seperate folders within the root folder of your application.

Extra files that will need to be distributed with your application:

gsgetfile.dll

If you plan on using the GetFile() or PutFile() functions, you might want to distrbute this file along with your application. This .dll file will provide a nice file dialog selection that is an improvement over the standard Windows Mobile or PocketPC OS default dialog.

sqlite_pc.dll or sqlite_ppc.dll

If you use any SQLite functions within your application, these two files will need to be included in the root folder of your application. Be careful because there are two seperate sqlite_dll.dll files. One is for the PC and the other is for the PocketPC. The SQL.PPL library file will load the correct one depending on the version of the executable. It's preferable to provide the correct one for each platform.

vgarom.fnt

This is the default font used by the GameAPI. If you make a game or an application that uses the GameAPI you will need to include this file in the root folder of your application else the FPS and default fonts won't appear on the screen.

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

PIDE Shortcut Keys

Written By Akki

PIDE Shortcut Keys

Shortcut keys in the PIDE by Brad Manske

By now you've opened up PIDE and used it for a while. Hopefully everyone has noticed the
keyboard shortcuts placed in the menus. Here are a few that are very helpful, but not so
obvious.

In PIDE's Game Level Editor try + while a sprite is selected, this will
Create a new sprite copying the original sprites properties.

In PIDE's Visual Form Builder:

  • The key will select the Form Control.
  • If you need a little help, F1 will bring up VFB Help and +F1 will bring up the MSDN help for the selected control.
  • Hold down the key and move the mouse over the form. This will show dashed lines from the mouse position to the ruler to help align controls on the form.
  • Arrow keys can move a control by 1 pixel at a time to get things lined up perfectly.
  • When editing controls that can use a list (GroupBox, ListBox, TabControl, etc...) select "Caption" in the properties and then press F5. You can enter values to preload into these control.
  • If you need to select a color for the properties, use F4.
  • If you need to select a filename for the properties, use F3.
  • If you need to select a true/false value for properties, +T will enter true and +F will enter false.

For those of you that are not keyboard jockies, right click on the properties to bring up the context
menu with the options for the properties.

Here is a reference card for those who could use it

PIDE Editor ShortCut Keys:

  -N           New
-O Open
-S Save file
-P Print
-Z Undo
-Z Redo
-X Cut
-C Copy
-V Paste
Delete
-C Comment Code
-R RGB color
-D Format Code
-G Goto Line Number
-F Find
-F Find in Files
-F3 Find Again
-H Replace
-F11 Find Definition
-F11 Open Selected File
-F8 Line Profile Result
-F7 Run
-F9 Dedicated Run
F7 Compile
F5 Debug
F10 Step Over
F11 Step Into
-F10 Run to Cursor
-F5 Stop
F9 Toggle Breakpoints
-B Breakpoint Window
-F7 Watches Window
-F12 File Manager
F12 Visual Form Builder
-G Procedures List
F4 Goto Map...
Clear a controls code.
F1 Help
-F1 MSDN Help

PIDE VFB ShortCut Keys:

  F1                 VFB Help
+F1 MSDN help on selected control
F3 Select FileName for properties
F4 Select Color for properties
F5 Edit List of values for control
Focus on the Form Control
Show Alignment lines
+T Enter True for properties
+F Enter False for properties
Move selected control by one pixel.

PIDE Game Level Editor ShortCut Keys:

  +    create a copy of the selected sprite.

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb

Tutorial 13 - Game API #1

Written By Akki

Tutorial 13 - Game API #1

PPL Game Programming - Part 1 - Game code structure.

PPL comes with a very powerful set of gaming functions called the GameAPI. The GameAPI comes in two different flavors. The first is the standard edition which does not contain the physic engine and the particles engine. You can create very nice games without them as well. In this first article of the series, we will concentrate on how games are handled in PPL.

Designing a game is a long and tedious process. You have to lay down your plan well in advance before even writing a single line of code. When it comes time to write the game you are often presented with low-level functions where you have to create custom routines to handle your particular kind of game. Writing a game engine requires good knowledge and time. With PPL, you can cut this step, saving days, weeks even months of hard work. The GameAPI will offer plenty of power for any type of 2D game programming.

The first step when you write a game with PPL is to start with a solid code structure that you will use as your starting template for all your future projects, unless you use the Game Level Editor that comes with the PIDE, the code generated by the GLE (Game Level Editor) has the same basic code structure as you will have here.

Let's review our code structure:

#include "GameAPI.ppl"
func mainproc(hWnd$, Msg$, wParam$, lParam$)
ok$ = true;
  case (Msg$)
    WM_CLOSE:
ShutGameAPI(hWnd$);
    WM_KEYDOWN:
g_KeyEvent(wParam$, True);
    WM_KEYUP:
g_KeyEvent(wParam$, False);
  end;
  return (ok$);
end;
func GameProc(hWnd$, Msg$, wParam$, lParam$)
case (Msg$)
WM_PAINT:
G_Clear(0);
RenderSprites;
    WM_TIMER:
if (g_key.vkA$)
PostMessage(hWnd$, WM_CLOSE, 0, 0);
end;
  end;
return (true);
end;
func WinMain
h$ = newform(, , &mainproc);
ShowWindow(h$, SW_SHOW);
  InitGameAPIEx(h$, &GameProc, 240, 320, false, 5, 60);
ShowFPS(true, G_RGB(255, 255, 255));

return (true);
end;

At the first line of code we include the GameAPI library into our project. This is where most of the GameAPI constants are defined. Some really handy functions are defined in as well. The mainproc function is where all GameAPI events are handled. The first event we will handle by default is the WM_CLOSE, which is triggered when the GameAPI main form is closed. Here we need to shutdown the GameAPI by calling ShutGameAPI(hWnd$). It is generally here that you will free all global objects. Sprites are freed by the function automatically. If you load surfaces manually, it is a good place to free them. Next we handle the WM_KEYDOWN and WM_KEYUP events. When a key is pressed (hardware keys on the PocketPC device), a keydown is triggered, then when the key is released, the keyup event is triggered. This code is pretty standard, a special function is called to set the g_key$ structure values, then you can easily check to see which key is being pressed and it supports multiple key presses too.

Next, every game as to have a main code function. At every internal cycle this function will be called. This is where you will handle game specific events like painting and timer. The painting can be handled manually using the WM_PAINT event or if you set the G_AutoDraw(True) right after the InitGameAPIEx() line, PPL will handle the drawing of sprites for you. If you use manual painting, the whole screen as to be repainted, that is why we clear the screen with G_Clear(0). Zero is the color of the background, black in this case. The RenderSprites() function will paint all sprites on screen with the correct layer order and everything. The WM_TIMER is called every game code cycle. We will see later how to change the cycle rate with the SetAISpeed() function. Here is a good place to check for key pressed. In our case if the hardware A key is pressed, we send a close message to the main game form.

The WinMain function is where PPL will start executing instructions for this program. Here we need to create a new form, display it using the ShowWindow() function. Next we need to initialize the GameAPI and the sound engine. InitGameAPIEx() will do all this work for us. We need to tell it what form will be used for the game display (h$), which main game code function to use (&GameProc), the resolution of the game (240x320 QVGA), the fullscreen parameter as to be false. Next is the cycle rate at which to call the WM_TIMER event in the main game function (&GameProc). Every 5 milliseconds PPL will try to trigger the WM_TIMER event. The last parameter is the maximum frames per second to display. 60 is a good generic value, it's smooth, gives time to the main game code to be executed and won't slow down the game by trying to draw unnecessary frames. Next we want to display the FPS (frames per second) information on screen. You might want to turn this off when your game is finished and you are ready to distribute it.

Finally we return a value of true to tell PPL to keep the application alive that it hasn't been closed.

This is a very basic game code structure. We will get into more details with sprites and their internal functions, pixel-perfect collision detection, sprite's mass, friction and velocity, particles and so much more as the series evolve. See you next month and happy game creation.

Share and Enjoy:
  • del.icio.us
  • StumbleUpon
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Reddit
  • Technorati
  • IndianPad
  • YahooMyWeb