March 18, 2024, 08:23:32 PM

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


Noob experiment #1

Started by Protected, May 24, 2006, 12:24:59 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Protected

class Entity : C2DSprite {
declare load (C2DScreen *scr, C2DSurface *cnv, string spri);
declare draw ();
C2DScreen *screen;
C2DSurface *canvas;
string sprite;
}

class World : C2DScreen {
declare OnTimer (int nIDEvent), int;
declare start ();
declare addEntity (string spr);
C2DScreen screen;
C2DSurface *canvas;
Entity temp;
}

World :: start () {
screen.CreateFullScreen (800,600,16);
canvas = screen.GetBack ();
canvas->Fill (RGB (0, 0, 0));
StartTimer (10);
return true;
}

World :: addEntity (string spr) {
temp.load (screen, canvas, spr);
}

World :: OnTimer (int nIDEvent) {
temp.draw ();
screen.flip(1);
return true;
}

Entity :: load (C2DScreen *scr, C2DSurface *cnv, string spri) {
screen = scr;
canvas = cnv;
sprite = spri;
C2DSprite !! Load (screen, getstartpath () + sprite, 0, 0, 1, false);
}

Entity :: draw () {
C2DSprite !! RenderXY (canvas, 20, 20);
}

global sub main () {
World game;
game.start ();
game.addEntity ("mouth.bmp");
while (!GetKeyState (0x01)) {}
return 0;
}


It compiles with no problems and mouth.bmp is in the right place, but nothing appears when I run the program. Any idea of what I did wrong? I'm thinking it's something in the pointers or inheritance  :-[

Ionic Wind Support Team

Your overcomplicating things.

World is derived from C2DScreen so there is no reason to have a C2DScreen member variable.  So for example in World::Start you would just have CreateFullScreen and not screen.CreateFullScreen since the world is derived.

Entity is derived from C2DSprite so there is no reason to do this:  C2DSprite !! RenderXY (canvas, 20, 20);   Simply use RenderXY.

When you derive a class you inherit all of its functionality.  Your class is a kind of the derived class.

You should also not be using the timer to flip things.  I only used it as an example to show you how it could be done.  But anyway your problem is in the timer.  You using screen.CreateFullScreen but are starting the timer in the derived 'World' class.  You basically have two windows there instead of just one.
Ionic Wind Support Team

Ionic Wind Support Team

Here is a working example.  You could structure this better of course but lets cover a few things.

#1. In DirectX you have to draw everything before calling Flip();.  This means your background (fill) your sprites (render), etc.  You can't just fill the surface once.  DirectX is a page flipper, you draw a complete page (the frame) and flip it to the front surface so the user can see it.  Then you do it all over again as fast as possible.

#2. Windows programs need message processing.  Flip allows messages to be processed after each frame is presented so if you wanted to call Flip in a timer you would need to be processing messages somewhere else.  The Wait(1) function for example.  Which is why your first try, even if you got rid of the errors, would never have worked.  You were opening a screen and looping while waiting for a mouse button, but nothing else.  No messages would have been processed so no OnTimer calls.

Have fun,
Paul.


class Entity : C2DSprite {
declare load (C2DScreen *scr, C2DSurface *cnv, string spri);
declare draw ();
C2DScreen *screen;
C2DSurface *canvas;
string sprite;
}

class World : C2DScreen {
declare OnTimer(int nIDEvent),int;
declare start ();
declare addEntity (string spr);
declare Update();
C2DSurface *canvas;
Entity temp;
}

World :: start () {
CreateFullScreen (800,600,16);
canvas = GetBack ();
StartTimer(100);
return true;
}

World :: addEntity (string spr) {
temp.load (this, canvas, spr);
}

World::OnTimer(),int
{
}

World :: Update () {
canvas->Fill (RGB (255, 0, 0));
temp.draw ();
flip(1);
}

Entity :: load (C2DScreen *scr, C2DSurface *cnv, string spri) {
screen = scr;
canvas = cnv;
sprite = spri;
if(C2DSprite!!Load (screen, getstartpath () + sprite, 0, 0, 3, true)  != 0)
{
//you need to set a render mode
SetRenderMode(RENDER_BLK);
}
}

Entity :: draw () {
RenderXY (canvas, 20, 20);
}

global sub main () {
World game;
game.start ();
game.addEntity ("mouth.bmp");
while (!GetKeyState (0x01)) {
game.Update();
}
return 0;
}
Ionic Wind Support Team

Protected

You're right, it was stupid to have the screen separated from the World ;D thanks for the corrections!

One question, why do I need a C2DSprite!! before the Load but no C2DScreen!! before the CreateFullScreen (and company) ?

Ionic Wind Support Team

Because you named the method 'load' and it tells the compiler to use the method from C2DSprite and not yours.  Name your method anything else such as "LoadEntity" and you can drop the base class scope resolution
Ionic Wind Support Team

Protected

Ahhh.... THis thing is case insensitive ~_~ I'll remember that. Thanks again!

Protected


World :: isRunning () {
return true;
}


global sub main () {
...
while (game.isRunning ()) {
game.update();
}
...
}


Why would I get an "invalid argument to WHILE statement" error here?

Protected

I got it. I forgot to specify the return type. Sorry ~_~ The error message was misleading!