IonicWind Software

Aurora Compiler => 2D Graphics => Topic started by: Ionic Wind Support Team on May 17, 2006, 05:11:19 PM

Title: Frags example.
Post by: Ionic Wind Support Team on May 17, 2006, 05:11:19 PM
Not just a 2D example, but an example showing one of the many ways you can structure an application in Aurora.  In this program there is a main class called TheApp.  TheApp class contains the variables and functions required to make everything work.  The main() function consists of only two lines...create an instance of TheApp and pass control to it's Run() member function.

This is very similar to how MS Visual Studio creates applications.

Anyway enjoy the pretty colors ;)


/*
The frags demo.  Hold down the left mouse button and move around to generate the fragments.
Press ESC to exit.
For Aurora Alpha 3 or greater
*/
#define width 640
#define height 480
#define intensity 20

struct Frag {
float x;
float y;
float xs;
float ys;
int r;
int g;
int b;
}

class TheApp
{
declare TheApp();
declare _TheApp();
declare CreateFrags(int mx,int my);
declare UpdateFrags();
declare RenderFrags();
declare Run(),int;
//variable of the app
C2DScreen screen;
CPointerList frags;
float gravity;
int ptx,pty,speed;
}

TheApp::TheApp()
{
gravity = .1f;
temp = 0;
ptx = 0;
pty = 0;
done=0;
speed = 0;
//create the linked list of frags.
frags.Create();
}

TheApp::_TheApp()
{
frags.RemoveAll(true);
}

TheApp::Run(),int
{
//Create the screen
if(screen.CreateFullScreen(width,height,32) < 0)
{
MessageBox(0,"Couldn't creat the screen..sorry","Error");
return false;
}
//turn off the cursor
screen.SetCursor(CS_CUSTOM,0);
//get a pointer to the back buffer
C2DSurface *back = screen.GetBack();
do
{
back->Fill(0);
UpdateFrags();
ptx = screen.MouseX();
pty = screen.MouseY();
if( GETKEYSTATE(0x01) )
CreateFrags(ptx,pty);
back->Lock();
back->DrawRect( ptx,pty-3,1,7,RGB(255,255,255) );
back->DrawRect( ptx-3,pty,7,1,RGB(255,255,255) );
RenderFrags();
back->Unlock();
screen.WriteText(4,20,"FPS: " + NumToStr(speed,0) + " Esc to exit");
speed = screen.Flip(1);

}Until GetKeyState(0x1B);
screen.CloseScreen();
return true;
}

TheApp::UpdateFrags()
{
void *pos = frags.GetFirst();
while pos
{
Frag *f = frags.GetData(pos);
f->x += f->xs;
f->y += f->ys;
f->ys += gravity;
If((f->x < 0) || (f->x >= width) || (f->y >= height))
{
pos = frags.Remove(pos,TRUE);
f = NULL;
}
Else If (f->b > 0)
{
f->b -= 5;
}
Else If (f->g > 0)
{
f->g -= 3;
}
Else If (f->r > 0)
{
f->r -= 1;
If f->r=0
{
pos = frags.Remove(pos,TRUE);
f = NULL;
}
}
if f <> 0
pos = frags.GetNext(pos);
}
}

TheApp::CreateFrags(int mx,int my)
{
int count = RAND(intensity)+intensity;
float an,anstep = 360.0f/count;
an=RND(anstep);
for(int k=1;k <= count; k++)
{
Frag *f = frags.Add(NEW(Frag,1));
f->x=mx;
f->y=my;
f->xs=FCosD(an) * (Rnd( 1 ) + 3f);
f->ys=FSinD(an) * (Rnd( 1 ) + 3f);
f->r=255;
f->g=255;
f->b=255;
an += anstep;
}
RETURN;
}

TheApp::RenderFrags()
{
C2DSurface *back = screen.GetBack();
void *pos = frags.GetFirst();
while(pos)
{
Frag *f = frags.GetData(pos);
back->DrawRect( f->x-1,f->y-1,3,3,RGB(f->r,f->g,f->b) );
pos = frags.GetNext(pos);
}
}

global sub main ()
{
TheApp app;
app.Run();
}
Title: Re: Frags example.
Post by: Doc on May 17, 2006, 10:25:50 PM
Cool! ...would make a really nice screen saver. :)

-Doc-
Title: Re: Frags example.
Post by: kryton9 on May 18, 2006, 06:43:25 AM
Thanks for the sample! Fun to play with.

Trying the gravity at .01f  really cool effects depending on the length of the mouse being held down and moved around.

But I am lost reading the code. This class stuff is fun, if you look at it as a challenge. So many myapps defined, declared assigned used. I guess when I understand this I will get the hang of this class stuff.

What I don't get is the classes are in the source file but when I use the class viewer I don't see them in there? And in other examples I see the resources in the resource viewer but I get errors compiing with the linker and resources, Peaslee's Skeleton example is one for example.

Title: Re: Frags example.
Post by: Ionic Wind Support Team on May 18, 2006, 07:11:51 AM
Class Viewer isn't finished yet. 
Title: Re: Frags example.
Post by: kryton9 on May 18, 2006, 07:41:57 PM
ahh, glad to hear that as I thought I was really out of touch in not getting it to work :)  Now I am inspired to keep reading the samples and figuring it out, thanks for a great example to look at though and play with. It is really fast.
Title: Re: Frags example.
Post by: Ionic Wind Support Team on May 18, 2006, 09:00:04 PM
Your welcome ;)
Title: Re: Frags example.
Post by: Protected on May 19, 2006, 09:11:43 AM
Just a warning - I have alpha 3 rev 1 and this code does not compile here. Maybe it requires rev 2? I can't test that just yet, I want to spend my rev 1 trial entirely before moving to 2 :P

(Can't pay the license yet)

EDIT: A clarification: The compiler goes into infinite cycle when compiling it.
Title: Re: Frags example.
Post by: Ionic Wind Support Team on May 19, 2006, 09:16:24 AM
Should work on Rev 1.  Don't know as we are way past that ;)
Title: Re: Frags example - Scope questions
Post by: Haim on May 20, 2006, 09:06:47 AM
I was playing with the frags example, trying to understand the TheApp class. I am just beginning oop, so my questions are probably stupid. my apologies for that...

1. In the example, the variable app, which is an instance of TheApp is defined in sub main. Why,  when I moved it outside of main (like a global variable), the program would not run, resulting in a GPF.
It seems as if variable app is not "recognized" from outside main()

2. I created an application with a CApp class, similar to the one in the frags example. The class was instantiated in main(), like in the frags example.
I also created  class MyWin, derived from Cwindow and put an instance of it as a member variable of CApp.
I was unable to access CApp from MyWin.
Is it possible to access CApp from the MyWin class (which is a member of CApp?)


Haim

Title: Re: Frags example.
Post by: Parker on May 20, 2006, 09:54:06 AM
You can't create a class globally, because then the compiler would have to put the constructor call somewhere, and if that module doesn't have main() inside it, that would be almost impossible.

You can place class variables in a function body or inside another class, and you can put a pointer to a class anywhere and manually new/delete it.

You can't really do anything with a class right now, much more than the MyClass!!SomeMethod to forward processing, but if you have a member variable, you should be able to do something like m_theApp.Run();.
Title: Re: Frags example.
Post by: Haim on May 20, 2006, 10:00:50 AM
Thanks for the explanation.
Haim
Title: Re: Frags example.
Post by: Ionic Wind Support Team on May 20, 2006, 10:28:30 AM
Just to clarify.  You can use global classes, but the compiler doesn't call the default constructor currently.  You can call the constructor yourself though.

#2.  by a bit of class magic you can accomplis this.  In other OOP languages they use a global pointer.


class MyAPP
{
   declare Run();
   //app variables
   MyWin win;
   int some_variable;
}

global gpMyApp;
MyAPP *gpMyApp;  //a global pointer to the app class

global sub main()
{
    MyApp app;
    gpMyApp = app;
    app.Run();
}



The from a method of MyWin you can use this global pointer.


MyWin::OnCreate(),int
{
gpMyApp->some_variable = 2;
}


I should note that the frags example shows only one of the many ways to structure an OOP application.  Having an "App" class that is the super class of the application tends to make the program a bit easier to manage.  You don't need to use it obviously. 

Paul.
Title: Re: Frags example.
Post by: Haim on May 20, 2006, 10:51:09 AM
Wow!ÂÃ, Got it.
Thanks,

Haim
Title: Re: Frags example.
Post by: Protected on May 20, 2006, 12:45:06 PM
I'm learning a lot from this example, but I have a question about the creation of instances:

global sub main ()
{
TheApp app;
app.Run();
}


Frag *f = frags.Add(NEW(Frag,1));

This is confusing me a little. You use NEW for a struct? What exactly does it do? Does the creation of instances of classes not require NEW? Are they automatically created when you declare a variable whose type is that class? Are they automatically destroyed as well? If not, how are they destroyed? I've been looking mostly at screens and they seem to have their own methods but I'm not sure all classes work the same, or what's the standard behavior. In the meantime I'll keep poking around :P
Title: Re: Frags example.
Post by: Parker on May 20, 2006, 01:39:00 PM
New can be used on any variable type - struct, class, intrinsic. It calls __NEW which allocates memory for that item, and if what you're calling it on is a class, it calls the constructor for that class.

Local class variables are constructed where they appear, globals aren't because global code isn't actually executed like it is in BASIC.
Title: Re: Frags example.
Post by: Protected on May 20, 2006, 02:06:13 PM
Hm, I think I get it, thanks. What happens if I construct a class twice, then? Any invisible effects? Memory leakage and stuff?
Title: Re: Frags example.
Post by: Parker on May 20, 2006, 02:15:29 PM
Just the same memory loss as you normally would have, unless the class does some operation and then automatically deletes itself.

The code pSomeClass = new( SomeClass, 1 ); does this:
pSomeClass = calloc( 1, sizeof( SomeClass ) );
SomeClass::SomeClass( pSomeClass );
where the constructor's parameter is the "this" pointer. So if you call new twice in a row without deleting it, you're passing a new instance to the constructor each time, since the value returned from calloc (or in Aurora's case GlobalAlloc) will be different each time.
Title: Re: Frags example.
Post by: Protected on May 20, 2006, 02:19:31 PM
SO if you go:

pSomeClass = new( SomeClass, 1 );
pSomeClass = new( SomeClass, 1 );

(for example, no one would do anything so stupid, of course)

one instance of the class would be created and then lost (have no pointer to it), right? Would it be destroyed or would it be needlessly using memory?
Title: Re: Frags example.
Post by: Mike Stefanik on May 20, 2006, 02:49:58 PM
If you use new then the object (intrinsic type, structure or class) is created on the process heap and that object persists beyond the method that it is created in. You release the memory allocated from the heap using delete. For example, let's consider a simple class and a function to create an instance of an object and initialize it:


class CMyClass
{
ÂÃ,  ÂÃ,  declare CMyClass();
ÂÃ,  ÂÃ,  declare MyFunction(), int;

ÂÃ,  ÂÃ,  int m_nValue1;
ÂÃ,  ÂÃ,  int m_nValue2;
}

CMyClass::CMyClass()
{
ÂÃ,  ÂÃ,  m_nValue1 = 0;
ÂÃ,  ÂÃ,  m_nValue2 = 0;
}

CMyClass::MyFunction(), int
{
ÂÃ,  ÂÃ,  return (m_nValue1 + m_nValue2);
}

sub CreateInstance(int nParam1, int nParam2), pointer
{
ÂÃ,  ÂÃ,  CMyClass myClass;

ÂÃ,  ÂÃ,  // Initialize the instance of CMyClass
ÂÃ,  ÂÃ,  myClass.m_nValue1 = nParam1;
ÂÃ,  ÂÃ,  myClass.m_nValue2 = nParam2;

ÂÃ,  ÂÃ,  return &myClass;
}


This would be the wrong way to do this because the instance of CMyClass (named "myClass") is being created locally on the stack and it goes out of scope as soon as the function returns. In other words, the pointer that is being returned will no longer point to a valid object.

The correct way to implement that code would be as:


class CMyClass
{
ÂÃ,  ÂÃ,  declare CMyClass();
ÂÃ,  ÂÃ,  declare MyFunction(), int;

ÂÃ,  ÂÃ,  int m_nValue1;
ÂÃ,  ÂÃ,  int m_nValue2;
}

CMyClass::CMyClass()
{
ÂÃ,  ÂÃ,  m_nValue1 = 0;
ÂÃ,  ÂÃ,  m_nValue2 = 0;
}

CMyClass::MyFunction(), int
{
ÂÃ,  ÂÃ,  return (m_nValue1 + m_nValue2);
}

sub CreateInstance(int nParam1, int nParam2), pointer
{
ÂÃ,  ÂÃ,  CMyClass *pMyClass = new(CMyClass, 1);

ÂÃ,  ÂÃ,  // Initialize the instance of CMyClass
ÂÃ,  ÂÃ,  pMyClass->m_nValue1 = nParam1;
ÂÃ,  ÂÃ,  pMyClass->m_nValue2 = nParam2;

ÂÃ,  ÂÃ,  return pMyClass;
}


This is correct because the instance of the object is being created on the heap, and it will persist after the CreateInstance function returns. Once the instance of the CMyClass object is no longer required, you'd release it using delete. For example:


CMyClass *pClass = null;
int nResult = 0;

pClass = CreateInstance(10, 20);
if (pClass != null)
{
ÂÃ,  ÂÃ,  nResult = pClass->MyFunction();
ÂÃ,  ÂÃ,  delete pClass;
}

print("The result is ", nResult);

Title: Re: Frags example.
Post by: Mike Stefanik on May 20, 2006, 02:54:14 PM
Quote from: Protected on May 20, 2006, 02:19:31 PM
SO if you go:

pSomeClass = new( SomeClass, 1 );
pSomeClass = new( SomeClass, 1 );

(for example, no one would do anything so stupid, of course)

one instance of the class would be created and then lost (have no pointer to it), right? Would it be destroyed or would it be needlessly using memory?

In languages like Java and C#, which have garbage collection, it would be automatically destroyed when the reference count to that object dropped to 0. In languages like C++ and Aurora, you would have to explicitly call delete between those two calls, otherwise you "lose" the first instance of the object and it won't be destroyed until the process terminates (in other words, you would have a memory leak).

In short, for every call to new, you must have a matching call to delete.
Title: Re: Frags example.
Post by: Protected on May 20, 2006, 02:58:11 PM
Aha. So if there is a class inside another class - or in other words, a class whose instance is automatically created - and I call NEW on it afterwards, it would also cause a problem like this, right?

EDIT: Call NEW on it only once.
Title: Re: Frags example.
Post by: Mike Stefanik on May 20, 2006, 03:14:16 PM
You can actually declare an instance an inner class without needing to allocate it dynamically, since the outer class that contains it is being allocated on the heap. For example, this is perfectly fine:


class CInnerClass
{
    declare CInnerClass();
    declare _CInnerClass();
    declare DoSomething();
}

CInnerClass::CInnerClass()
{
    writeln("The constructor for CInnerClass has been called\n");
    return;
}

CInnerClass::_CInnerClass()
{
    writeln("The destructor for CInnerClass has been called\n");
    return;
}

CInnerClass::DoSomething()
{
    writeln("The DoSomething method for CInnerClass has been called\n");
    return;
}

class COuterClass
{
    declare COuterClass();
    declare _COuterClass();
    declare DoSomething();

    CInnerClass m_innerClass;
}

COuterClass::COuterClass()
{
    writeln("The constructor for COuterClass has been called\n");
    return;
}

COuterClass::_COuterClass()
{
    writeln("The destructor for COuterClass has been called\n");
    return;
}

COuterClass::DoSomething()
{
    writeln("The DoSomething method for COuterClass is calling CInnerClass::DoSomething\n");
    m_innerClass.DoSomething();
    return;
}

global sub main
{
    COuterClass *pClass = new(COuterClass, 1);
    if (pClass != null)
    {
        pClass->DoSomething();
        delete pClass;
    }

    while (GetKey() == "");
    return;
}

Title: Re: Frags example.
Post by: Mike Stefanik on May 20, 2006, 03:19:34 PM
You could also implement that as:


class CInnerClass
{
    declare CInnerClass();
    declare _CInnerClass();
    declare DoSomething();
}

CInnerClass::CInnerClass()
{
    writeln("The constructor for CInnerClass has been called\n");
    return;
}

CInnerClass::_CInnerClass()
{
    writeln("The destructor for CInnerClass has been called\n");
    return;
}

CInnerClass::DoSomething()
{
    writeln("The DoSomething method for CInnerClass has been called\n");
    return;
}

class COuterClass
{
    declare COuterClass();
    declare _COuterClass();
    declare DoSomething();

    CInnerClass *m_pInnerClass;
}

COuterClass::COuterClass()
{
    writeln("The constructor for COuterClass has been called\n");
    m_pInnerClass = new(CInnerClass, 1);
    return;
}

COuterClass::_COuterClass()
{
    if (m_pInnerClass)
        delete m_pInnerClass;

    writeln("The destructor for COuterClass has been called\n");
    return;
}

COuterClass::DoSomething()
{
    writeln("The DoSomething method for COuterClass is calling CInnerClass::DoSomething\n");
    m_pInnerClass->DoSomething();
    return;
}

global sub main
{
    COuterClass *pClass = new(COuterClass, 1);
    if (pClass != null)
    {
        pClass->DoSomething();
        delete pClass;
    }

    while (GetKey() == "");
    return;
}


If you run this example and the previous one, you'll notice a subtle difference. The advantage of creating the inner class dynamically is that it gives you control over when the instance of the inner class object is created and destroyed. Otherwise, as in the previous example, it's handled automatically.
Title: Re: Frags example.
Post by: Protected on May 20, 2006, 03:23:29 PM
Oooooh, pointers... I see... I didn't have to deal with such things in Java ;P

I understand now, this is all very flexible! I'll have fun playing with it in the next days, I guess  ;D Thanks for the examples!
Title: Re: Frags example.
Post by: Parker on May 20, 2006, 04:06:49 PM
Because java only works with references and has a garbage collector. It works well with an interpreted language like Java, but generally you use a compiled language for speed and versatility, not hiding you from the real details and extra code injected into your program.
Title: Re: Frags example.
Post by: Protected on May 20, 2006, 06:46:31 PM
Yes, Java is the slowest language I've ever used. I never compared it with IBasic standard, but it probably ends up being slower. That's why Aurora is the perfect language for what I want to do!

I'm brainwashed against C++, teachers in my university don't like it. Too many weird combinations of symbols, they say ;P I think they'd make us write everything in assembly if they could, but since they can't, it ends up being mostly C!
Title: Re: Frags example.
Post by: Mike Stefanik on May 20, 2006, 09:56:09 PM
Quote from: Protected on May 20, 2006, 06:46:31 PM
I'm brainwashed against C++, teachers in my university don't like it.

I've heard of some universities that don't like to teach C++ because its not a "pure" OOP language and prefer to teach using Smalltalk, or that it's not "safe" and think it's better to teach Java or C#. But to not teach it because of it's syntax? Ouch. At least they do teach C, and while assembly language may seem archaic, it's important to at least have a fundamental understanding of things like registers, stack frames, pointers, etc. With the advent of Java and C#, there's going to be a generation of programmers coming up that don't really understand how pointers work, what heaps are and how to manage memory and how the core Windows operating system actually functions. They see a world of classes and object references, with virtual methods that get magically invoked without any real fundamental understanding of what's going on inside the "black box" so to speak. I'm not sure that's such a good thing.
Title: Re: Frags example.
Post by: Protected on May 21, 2006, 04:57:07 AM
Quote from: Mike Stefanik on May 20, 2006, 09:56:09 PM
With the advent of Java and C#, there's going to be a generation of programmers coming up that don't really understand how pointers work, what heaps are and how to manage memory and how the core Windows operating system actually functions. They see a world of classes and object references, with virtual methods that get magically invoked without any real fundamental understanding of what's going on inside the "black box" so to speak. I'm not sure that's such a good thing.

Well, we computer engineers (in my university) are required to learn how computers work from the transistor and up. Not only we studied circuits, processors and memory, but we also had to write a pong game in assembly (in a simulator) and our first class on algorithms (sorting and search) and data structures was in C. We also learned synchronization and sockets in C, and right now we're writing a compiler. Expect me to bug you partner developers when the conflicts in yacc become too frustrating  ;D I still don't know how to properly write the shift/reduce/goto table of LR grammars on paper... Fortunately it will only come for my second test which is in July 1. Last year Paul gave me some valuable tips to solve the conflicts with the if and while blocks and we managed to pass the project with 15/20 (and that's without the compiler having all the required functionality :P). Unfortunately I failed the theoretical exam.

We use Java and LISP and such in classes about programming paradigms, design patterns or higher level programming, like 3D object rendering and AI.

EDIT: On the other hand, we learn NOTHING of Windows. It's all linux there  ::)

Title: Re: Frags example.
Post by: Parker on May 21, 2006, 11:02:18 AM
If you're doing compilers, you may want to (if you don't already have it) get the dragon book. (http://www.amazon.com/gp/product/0201100886/sr=8-1/qid=1148230632/ref=pd_bbs_1/104-5515296-6167164?%5Fencoding=UTF8&s9r=8a580aa70a22231f010a4675d0720003) There are some cheap (much less than $110) copies there, I got a new one for $30 a couple weeks ago.

I have to say that after using pointers and having to worry about freeing memory, it is kind of nice to program in java or C# where I can just say x=new X(); and not track down where I don't need it anymore, but I really think that everyone should learn C++ or C first, or any other language that requires you to delete/free the memory and work with actual pointers. Even though I said it's nice, I really prefer working in Aurora and C++ over java and C#. One thing I really hate is the forcing you to use classes when a procedural implementation would do just fine.
Title: Re: Frags example.
Post by: Protected on May 21, 2006, 01:04:28 PM
The Dragon book is supposed to be our only reliable book source (although it's said to be 'heavy'), but I never found it here in Portugal (it's always sold out) and I never bothered to order it yet. My teacher is very good, so I could make it with just the theoretical lessons if I hadn't missed two or three of them for... valid reasons ;P There is a portuguese book we can use but the teacher continuously reminds us of the opinion he has of it - Basically, it's a complete piece of crap, it seems the author of the book didn't really know what he was writing about, so I don't want to risk it...
Title: Frags Example alt
Post by: kryton9 on August 08, 2006, 08:11:17 PM
I look at the frag's example a lot and am using it heavily in my studies of Aurora, but was confused by it also. Anyways, today I got it to where I wanted it, to use it as a base for some cooler things with it in the near future.
Thought it might help others in the same boat and wanting to play with this stuff, so here is the base code:
/* Compile as Windows
The frags demo.ÂÃ,  Hold down the left mouse button and move around to generate the fragments.
Press ESC to exit.
For Aurora Alpha 3 or greater
*/


class Frags
{
declare Frags();
declare _Frags();
declare CreateFrags(int mx,int my);
declare UpdateFrags();
declare RenderFrags();
declare Run(),int;
//variable of the app
C2DScreen screen;
C2DSurface *back;
CPointerList pListOfFrags;
void *pos;
float gravity;
int ptx,pty,speed;
int width;
int height;
int intensity;
struct FragsStruct
{
float x;
float y;
float xs;
float ys;
int r;
int g;
int b;
}
FragsStruct *f;
}

Frags::Frags()
{
gravity = .1f;
temp = 0;
ptx = 0;
pty = 0;
done=0;
speed = 0;
width = 640;
height = 480;
ÂÃ,  ÂÃ,  intensity = 20;
//create the linked list of frags.
pListOfFrags.Create();
}

Frags::_Frags()
{
pListOfFrags.RemoveAll(true);
}

Frags::Run(),int
{
//Create the screen
if(screen.CreateWindowed(0,0,width,height,AWS_VISIBLE | AWS_POPUP ,0,"test",0) < 0)
{
MessageBox(0,"Couldn't creat the screen..sorry","Error");
return false;
}
//turn off the cursor
screen.SetCursor(CS_CUSTOM,0);
//get a pointer to the back buffer
back = screen.GetBack();
do
{
back->Fill(0);
UpdateFrags();
ptx = screen.MouseX();
pty = screen.MouseY();
if( GETKEYSTATE(0x01) )
CreateFrags(ptx,pty);
back->Lock();
back->DrawRect( ptx,pty-3,1,7,RGB(255,255,255) );
back->DrawRect( ptx-3,pty,7,1,RGB(255,255,255) );
RenderFrags();
back->Unlock();
screen.WriteText(4,20,"FPS: " + NumToStr(speed,0) + " Esc to exit");
speed = screen.Flip(1);

}Until GetKeyState(0x1B);
screen.CloseScreen();
return true;
}

Frags::UpdateFrags()
{
pos = pListOfFrags.GetFirst();
while pos
{
f = pListOfFrags.GetData(pos);
f->x += f->xs;
f->y += f->ys;
f->ys += gravity;
If((f->x < 0) || (f->x >= width) || (f->y >= height))
{
pos = pListOfFrags.Remove(pos,TRUE);
f = NULL;
}
Else If (f->b > 0)
{
f->b -= 5;
}
Else If (f->g > 0)
{
f->g -= 3;
}
Else If (f->r > 0)
{
f->r -= 1;
If f->r=0
{
pos = pListOfFrags.Remove(pos,TRUE);
f = NULL;
}
}
if( f )
pos = pListOfFrags.GetNext(pos);
}
}

Frags::CreateFrags(int mx,int my)
{
int count = RAND(intensity)+intensity;
float an,anstep = 360.0f/count;
an=RND(anstep);
for(int k=1;k <= count; k++)
{
f = pListOfFrags.Add(NEW(FragsStruct,1));
f->x=mx;
f->y=my;
f->xs=FCosD(an) * (Rnd( 1 ) + 3f);
f->ys=FSinD(an) * (Rnd( 1 ) + 3f);
f->r=255;
f->g=255;
f->b=255;
an += anstep;
}
RETURN;
}

Frags::RenderFrags()
{
back = screen.GetBack();
pos = pListOfFrags.GetFirst();
while(pos)
{
f = pListOfFrags.GetData(pos);
back->DrawRect( f->x-1,f->y-1,3,3,RGB(f->r,f->g,f->b) );
pos = pListOfFrags.GetNext(pos);
}
}

global sub main ()
{
Frags App;
App.Run();
}
Title: Re: Frags example.
Post by: Ionic Wind Support Team on August 08, 2006, 08:37:50 PM
Just so you don't get more confused.  A struct is just a definition.  Putting it within the class defintion does nothing more for you than having it outside the defintion, no more then putting a #define within a class defintion would.
Title: Re: Frags example.
Post by: J B Wood (Zumwalt) on August 08, 2006, 08:51:14 PM
Actually putting a struct within a class makes it a member of the class, so you have to make an instance of the class to use it.
right?
Title: Re: Frags example.
Post by: kryton9 on August 08, 2006, 08:55:54 PM
And this way it is protected from being altered by outside functions, right? In addition it looks slick and all OOPy :)
Title: Re: Frags example.
Post by: Ionic Wind Support Team on August 23, 2006, 01:11:32 PM
A varaible can be part of a class, and that varaible can be a structure type.  But the definition of a structure is just that, a defintion.  Doing this:

class myclass
{
  struct mystruct
  {
  }
}

Is no different than

struct mystruct
{
}

class myclass
{
}

Which was the point I was trying to make, having the structure defintion within a class defintion doesn't give you any benefit whatsoever. However.

class myclass {
   mystruct str1;  //  this is a member variable of type 'mystruct'. 
}

Then your statement would be true.  'str1' is only accessable from an instance of the class.