PDA

View Full Version : PPL 1.4/1.5 bugs and feature request after my first PPL game development


BSi
10-24-2006, 10:30 AM
Hi folks,

I'm just finished a small platform game development in PPL (see screenshots) and found a couple of small but annoying bugs in PPL. At the time I started the development, the active PPL version was 1.4 but I tested them under 1.5 as well. After a couple of tests I found workaround for every described problem except for the WM2005 one, but they're still exists and made me some headache.

1. SetSpriteCollideRect() problem #1
When using animated sprites, if I try to set a smaller collide rectangle than the sprite's actual dimensions, PPL will position the collision box badly.

2. SetSpriteCollideRect() problem #2
Let we use a small image which we can replicate horizontally to form a long repeating sprite. In my game this sprite type is the spikes on my platforms: I have a small spike image (10 pixel width) and I replicate it to form a continouos spike line. For the horizontal replication I use SetSpriteTileX(). As far as I know tiled sprites doesn't collides well because they're using the original sprite images dimensions for collide rectange. So I set the SetSpriteCollideRect() as well for this sprites, but when I check collision with Collide(), only the original image rectangle collides, not the given collide rectangle. It seems that the SetSpriteCollideRect() is ineffective in this case.

Another weird thing is if I use Collide() from opposite direction, it gives me different results. I'll explain it by the following example:
// test player
p$ = LoadSprite(AppPath$ + "player.bmp", -1, 1, 0, NULL);
MoveSprite(p$, x$, y$);
SetSpriteId(p$, "player");
SetSpriteCollide(p$, "spike");


// create spike (spike.bmp is 10x10 pixels)
s$ = loadsprite(AppPath$ + "spike.bmp", g_rgb(255, 0, 255), 1, 0, NULL);
MoveSprite(s$, x$, y$);
SetSpriteTileX(s$, 10);
SetSpriteOptions(s$, SO_COLLIDE | SO_CHECKCOLLIDE);
SetSpriteId(s$, "spike");
SetSpriteCollide(s$, "player");
SetSpriteCollideRect(s$, 0, 0, SpriteWidth(s$) * 10, SpriteHeight(s$));

a) Collide(s$, SpriteX(s$), SpriteY(s$), cx$, cy$)
It will detects collision only if player hits the original spike image rectangle (10x10 pixels).
b) Collide(p$, SpriteX(p$), SpriteY(p$), cx$, cy$)
It will detencts collision correctly, using the given collide rectangle.

3. Another collision weirdness
If I set a sprite to SO_FIXED or SO_FIXEDX, the engine calculates no collision with it at all.

4. WM2005 exe warning
If I compile my program to WM2003/WM2005, under my Windows Mobile 5.0 device the exe gives me the following startup warning always: "Runtime Error: This program was built on a different platform, it might not work properly!". Annoying.

5. SO_TOPMOST
When I set SO_TOPMOST to a sprite (actually to my level border), all of my sprites which are ever scrolled out of the screen will be immediately deleted by the engine. Strange and huge bug. For a workaround I use SetSpriteOrder() instead.

6. g_LoadFont(): font loading from file
If I try to load a font from a file (g_loadfont(AppPath$ + "font.ttf", 18, rgb(255,255,255), NULL)), I always got the following PPL runtime error:
App: test.ppl
File:test.ppl
Proc: WINMAIN
Opcode: G_LOADFONT
Char/Line/Offset: 12, 126, 0x01448910

(WINMAIN)
Access violation at 0x5c656d61
If I try to load the font from by it's name (refering to a system defined font), it will work well.

7. g_showmessage() and g_textout() without font definition
If I use g_showmessage() or g_textout() without exact font definition (ie: g_textout(NULL, "test", DVT_NONE, 1, 40, g_rgb(255, 255, 255))) it will leads to different result in the compiled exe and in the interpreted one. In the interpreted program it will shows the text with a default font, but in the compiled exe nothing appears in the screen.


After my first PPL game development I found that PPL is a really great language/tool for small 2D PPC game development but it's still young and have some limitations.

Also based on my first PPL game development I have two feature requests which could be handy for further development:

Request 1: AddSpriteCollide() / DelSpriteCollide()
AddSpriteCollide(): almost the same as SetSpriteCollide() but with AddSpriteCollide() you can define more than one collision group for a sprite to collide with.
DelSpriteCollide(): removes a collision group from the sprites collision check list

Request 2: CollideAll()
CollideAll() is almost the same as Collide() but it will return all of the colliding sprites, not only the first. (Actually I could write a CollideAll() function myself purly in PPL, using SpritesAt() and some manual low-level SpriteId and collision group checks, but it would be ineffective compared to a native language function.)


Finally here're the screenshots from my game:
../../e107_files/public/1161681906_97_FT0_js_screenshot1.jpg[br]
../../e107_files/public/1161681906_97_FT0_js_screenshot3.jpg[br]
../../e107_files/public/1161681906_97_FT0_js_screenshot4.jpg[br]
../../e107_files/public/1161682065_97_FT0_js_screenshot5.jpg

kornalius
10-24-2006, 06:06 PM
Wow, you should have contacted us way before finishing your game. We could have helped you one problem at a time. Now this is a huge list. You will have to help us a bit here.</p>

Please update your profile with your real name and serial #. Don't worry the serial # is not visible to others.*</p>

#1 and #2:</p>

They have been fixed in 1.06.</p>

#3:</p>

We just did some tests and collision works fine with SO_FIXED. Please give us more details.</p>

#4:</p>

We are looking into this issue.</p>

#5:</p>

We are try to fix this one right now.</p>

#6:</p>

This is normal. You need to pass the font name not a file name.</p>

#7:</p>

Again normal, the default VGA font needs to be copied over to the .exe folder. VGAROM.FNT.</p>

Request #1.</p>

This would be too complicated to implement in the current engine. We will look into it for a future version.</p>

Request #2:</p>

There is already a function called Collides() that does exactly this.</p>

kornalius
10-24-2006, 06:08 PM
Btw, nice screenshots. Are you going to apply for the contest?

BSi
10-25-2006, 12:55 AM
I've updated my profile as you asked.

First of all, let me thank you for your quick reactions. You're doing a great job with PPL it's good to see that you're fixing the language bugs almost immediately. Keep it up! So no bad feelings about these bugs at all, I know that PPL is a young language and young languages always have some children's illnesses. It's normal and expected. I'm a programmer too, and who can understand it more closely if not an other programmer? ;)

Anyway, actually I wrote this platform game in 3 days, so I have'nt wasted too mutch time working these bugs around. Eventually deadlines can make real miracles... :)

The main goal of creating this bug list is to inform you about them and to help you fix them.

Let we see:

#1, #2:

Great!

#3:

I've done some tests in 1.05 but I could'nt reproduce it either. Maybe you fixed it in the 1.04 -&gt; 1.05 update or maybe I overlooked something. Anyway, the problem is gone.

#4, #5:

Thanks.

#6:

Actually, regarding to the documentation I can give font file name (with or without absolute path) instead of font name to g_LoadFont(). The manual (CHM and HTML also) says:
FONT G_LOADFONT(string FontName, int Size, long Color, long Style)
Load a truetype font to be used with the GameAPI

Parameters

FontName {in}
If the font is installed in the fonts directory for the target OS, use the name (ex: &quot;Arial&quot;); if the font is in a custom path, use the file name and / or full path (ex: &quot;c:\\myfont.ttf&quot;)

[...etc...]

#7:

Good to know, thanks.

Request #1:

OK, I'm got the picture. I'm assure you It would be really appreciated :)

Request #2:

Great news but it would be more greater if you had documented it somewhere :)
In the documentation (CHM and HTML), there's no Collides() function at all. I've found some references for it only in the functions.dat file and nowhere else...

Game contest:

Thanks for your kind words, I'm think about it.

kornalius
10-25-2006, 04:28 PM
Hi,

#6: I've made the request for this to be corrected in the manual.

Request #2: Same thing the Collides() function will be added to the manual.

BSi
10-30-2006, 03:33 PM
Hi folks,

I'm just installed PPL 1.06 and it fixed some bugs while introducing others.

B#1: unwanted message
OK, it's actually not a real bug, but you left an unwanted line of code in LinkProcs.ppl:216
showmessage(&quot;num=&quot;+ic$);

B#2: SetSpriteCollideRect() bug
Well, SetSpriteTileX() now extends the collision rectangle of the sprite correctly, but if I use my previous code from 1.04/1.05 in which I set the collision rectangle manually, in 1.06 collision will be gone.
The example below collides well in 1.04/1.05 but not in 1.06:
// sample player
p$ = LoadSprite(AppPath$ + &quot;player.bmp&quot;, -1, 1, 0, NULL);
MoveSprite(p$, 50, 100);
SetSpriteWidth(p$, 28);
SetSpriteHeight(p$, 69);
SetSpriteId(p$, &quot;player&quot;);
SetSpriteCollide(p$, &quot;spike&quot;);

// sample spike
s$ = LoadSprite(AppPath$ + &quot;spike.bmp&quot;, -1, 1, 0, NULL);
MoveSprite(s$, x$, y$);
SetSpriteOptions(s$, SO_COLLIDE | SO_CHECKCOLLIDE);
SetSpriteId(s$, &quot;spike&quot;);
SetSpriteTileX(s$, length$);
SetSpriteCollideRect(s$, 0, 0, SpriteWidth(s$) * length$, SpriteHeight(s$) * height$); // this line is needed in 1.04/1.05 but 1.06 works only if I remove it

B#3: g_LoadFont()/g_DrawText() behavior changed
In 1.06 appeard a very annoying bug in font handlink and/or font drawing. If I load a custom font with g_LoadFont() and draw something to the screen using g_DrawText() the results will be different than in previous versions: there will be a black bounding box around (and behind) the drawn text. Weird.
The same code in 1.04/1.05: ../../e107_files/public/1162222063_97_FT981_js_fontbug1.jpg
...and in 1.06: ../../e107_files/public/1162222063_97_FT981_js_fontbug2.jpg

B#4: different build problems
I'm just discovered that PPL will create different executables while making exe on PocketPC and on PC's PIDE.

a) If I compile the exe on the PC (I choose target platform WM2003/WM2005 and tried compressed and uncompressed executables as well) and start the compiled exe on the PPC, it gives me the warning I posted already above: &quot;Runtime Error: This program was built on a different platform, it might not work properly!&quot;. Also if I use this exe, PPL cannot determine if 'vkA' hardware key is pressed on the PPC or not. Actually I made some debug and the case looks like PPL sets 'vkA' key's pressed state on every(!) hardware key press (not only when 'vkA' is pressed), but it remains set only in MainProc's WM_KEYDOWN section. If the program leaves this section, PPL shows that 'vkA' is not pressed at all. Other HW keys ('vkB', 'vkC', arrows and 'vkStart') behaves as expected, only 'vkA' is affected.

b) If I compile the exe on the PocketPC (either compressed or uncompressed executable) and run it, no runtime errors occure and the 'vkA' key is works as expected, no problems at all.

Thats all so far. Thanks in advance for the support kornalius.

kornalius
10-30-2006, 06:57 PM
Hi,

#1, this is known bug Brad told us how to remove it in another post.

#2. I am looking into it.

#3. This is my fault, I was doing some testing and forgot to put it back to normal. It will be back to normal in 1.07.

#4. We will look into it.

kornalius
10-30-2006, 07:26 PM
#1. Is fixed now.

#2. The following works ok:

setspritetilex(i$, 3);
setspritecolliderect(i$, 0, 0, 50, SpriteHeight(i$));

Are you sure your length$ variable contains a valid value?

#3. This is fixed now also.

BSi
10-31-2006, 07:37 AM
First of all thanks for your support.

#2: Yes, I'm sure I set length$ variable correctly and I just sent you a mail containing the details so you can test it yourself.

kornalius
10-31-2006, 11:52 AM
Hi BSi,

As per the email I just sent you. Your code now works perfectly. We found the problem. When no sprite collide is set on a sprite it was not properly added to the collision grid after a SetSpriteCollideRect is the collide rectangle set was the same as the original one.

BSi
10-31-2006, 02:15 PM
I see. Thanks again for the great support.

BSi
10-31-2006, 09:52 PM
Hi Alain,

I've recently found a new bug in the sprite showing/hiding code.
My goal is to hide a sprite and show an other sprite triggered by a keypress. The problem is that if I press the trigger key (&quot;vkStart&quot; in my example), the first sprite will be hidden, but the second one won't show up. Actually the bug is a little more nasty because when I hide the first sprite and try to show the second, PPL pauses (maybe freez). I don't know if it's a pause state or not, but I can assure you that in this case PPL stops responding for messages even in GameProc() and in MainProc() too.

Check out my attached code, it will reproduce the bug for you too. Please start the program and hit vkStart key to change sprites. I put some debug messages in MainProc() and GameProc() to check whats happens and when PPL freezes.[br]1162331457_97_FT981_test4.zip

PointOfLight
10-31-2006, 10:09 PM
I don't know if this will make a difference, but trying changing your WM_TIMER block to this:


WM_TIMER:
if (KeysPressed$[keys.vkA$])
PostMessage(hWnd$, WM_CLOSE, 0, 0);
end;

if (KeysPressed$[keys.vkStart$])
ShowSprite(p$, false);
debug(&quot;hide first sprite&quot;);
ShowSprite(s$, true);
debug(&quot;show second sprite&quot;);
end;

kornalius
11-01-2006, 05:41 PM
First of all, this type of key handling doesn't seem to fit well into the WM_TIMER. The reason why it doesn't like it's working is because it is happening too fast for you to really see what is going on.

I would put it in the WM_KEYDOWN, this way the event won't repeat a hundred times before the user can releasing the key.

There is a bug also that I am trying to fix as I write this. I'll get back to you with more info.

kornalius
11-01-2006, 06:49 PM
Ok the sprite sorting internal bug has been fixed.

BSi
11-01-2006, 10:29 PM
kornalius:
First of all thanks for the bugfix!

About the key handling I got the picture, you're right but this is only a bug test code and I took the skeleton from one of my other test apps in which the 'vkStart' key was responsible for my player's climb, and the player must climb continously while the key is pressed down.

PointOfLight:
Thanks for the suggestion but that definitely won't work in my code. I use the new style key handling in my code as you can see in my WM_KEYDOWN and WM_KEYUP, I use g_KeyEvent() to toggle a key's state and I don't bother setting/resetting KeysPressed$ global. Anyway both KeysPressed$ and g_KeyEvent() / g_key$ are declared in GameAPI.ppl so you can use either of them. The only difference is that KeysPressed$ is a simple array while g_key$ is a structure. I found g_key$ more elegant because while using the old style I need two globals (keys$ and KeysPressed$) instead using the new style I need only one (g_key$) and moreover it's a clear structure.

PointOfLight
11-01-2006, 10:57 PM
Actually, g_key$ and keys$ is the same structure. The only difference is that keys$ stores the code that the system returns when a particular key is pressed (ex: vkA$ may be 225 on the PPC, and 97 on the PC), whereas g_key$ holds the state of a particular key (ex: vkA$ might equal 0 or 1, depending on whether the key associated with vkA$ has been released or pressed). If you look at g_KeyEvent, it actually uses the keys$ variable, so you're still using two variables (either keys$ / g_key$ or keys$ / KeysPressed$). I'm not criticising the way you're doing it (in fact, that was something I didn't know, so thank you), I just wanted to point out that you're not saving as much as you think you are. Of course, you're right in that my solution wouldn't make a difference, then. I believe Kornalius was much more accurate when he said you shouldn't be using the WM_TIMER event to evaluate key presses.

kornalius
11-02-2006, 12:13 AM
For game design the WM_TIMER for key presses is the best solution. You want the key to repeat event every cycle while the key is pressed.

For a one-time key press solution, you can implement something that checks if the key was already pressed in a variable, if so, skip the code, when the key is not pressed anymore reset the variable.