GPWiki.org
GPWiki.org
It is currently Thu May 23, 2013 1:16 pm

All times are UTC




Post new topic Reply to topic  [ 24 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Mon Apr 09, 2012 10:25 am 
Shake'n'Baker

Joined: Thu Dec 29, 2011 2:33 pm
Posts: 62
Hi again,
this time a question, probably verify me as a total beginner*g*

Since I am trying something bigger this time(something like Mario, with only one screen. Just jumping, falling, basics),
I need some more variables.

The easiest way for me to handle all of them is
initialising them as globals.
I can edit and access them from everywhere,
no need to give them as a parameter for a function.
Con: It is not protected, can be changed from
everywhere, but I don't know why it is bad*g*

Secons idea is, that initialize them in the main loop
and use them as parameters for function always.
Arrays could be given as pointers.
Con: I think the chance to make syntax and logical errors is very high.

Third idea is making a class, holding all needed vars.
Making an instance and only use the pointer to the instance.


I hope you my thinking is rethinkable(is that a real word?*g*)
and you can help me with some tips :)

Thank you,
Aestond


Top
 Profile  
 
PostPosted: Mon Apr 09, 2012 11:28 am 
Harmlessness does no harm
User avatar

Joined: Tue Sep 14, 2004 8:37 pm
Posts: 3808
Location: Ferriday, LA, US
The problem with globals is that it makes it harder to deal with a project with any complexity. This is where data structures (such as classes and structs) come in handy -- they allow you to write a set of similar data once, and just re-use it whenever needed.

If you are using C++, you have access to classes in addition to structs (whereas in C, all you have is structs). Each will allow you to keep data relating to parts of your game (from everything to world maps to individual sprites) easier to manage, as every individual part of your game can be handled in a more flexible manner -- it is easier to manage individual objects, as well as object groups.

So, globals aren't necessarily "evil", but their usefulness is limited compared to the benefits of compartmentalizing data. Think of it has having a thousand items in your room with nothing to store your stuff in -- as opposed to having a few boxes and shelves. :)

As for pointers, you will need them at some point anyway. Also, look into passing references as arguments to functions, as opposed to passing pointers as arguments. Passing references is often preferable to passing a pointer, as it gives you the same benefit of reduced overhead (so that arguments are not copied by value when passed to a function), and can be easier to manage and less error-prone.

As for how these work together, you would normally use a class or struct as a "base" for your data. You can create one class, or one struct, and use it many times -- allowing you to create, for example, a particle sprite class, which would allow you to make a particle emitter that simply creates new particles based on that class (instead of having to individually create and initialize a new set of variables constantly). If you want to write a function that modifies an object directly, you can pass your object to that function via pointer (or reference) -- this will not only decrease overhead (since you are not building a new copy of the object), but allow you to access the memory space your argument occupies.

_________________
What most people don't understand about "enlightenment" is that it is not an end-goal; but where you find yourself just before taking a new "first step."


Top
 Profile  
 
PostPosted: Mon Apr 09, 2012 11:36 am 
Bytewise

Joined: Sun Oct 16, 2011 3:09 pm
Posts: 277
Location: Here (where else?)
aestond wrote:
this time a question, probably verify me as a total beginner*g*
Verified! :)
It is not a problem at all ;)

aestond wrote:
The easiest way for me to handle all of them is
initialising them as globals.
I can edit and access them from everywhere,
no need to give them as a parameter for a function.
Con: It is not protected, can be changed from
everywhere, but I don't know why it is bad*g*


The name of the global variable appears in the function code. That means if you have two variables that need the same kind of operation, you need to duplicate the function.
Duplicate code is bad, as one day you will find a bug, fix one, and forget you had a second one.

This is the basic reason why you want to use parameters, you want to avoid duplicate code at nearly all costs, as it will kill you (it eats development time by the months).

aestond wrote:
Secons idea is, that initialize them in the main loop
and use them as parameters for function always.
Arrays could be given as pointers.
Con: I think the chance to make syntax and logical errors is very high.
There is not much difference between a global and a main function variable. It costs the same amount of memory in both cases.

Passing variables through parameters has the advantage that the function does not care where the variable comes from, so you can avoid the problem I sketched above.
You can of course also pass global variables as parameter.


aestond wrote:
Third idea is making a class, holding all needed vars.
Making an instance and only use the pointer to the instance.
It's a kind of 'walking' global variables. Not useful imho.


aestond wrote:
I hope you my thinking is rethinkable(is that a real word?*g*)
and you can help me with some tips :)
The word is 'reconstructable' I think, and yes, your ideas are clear to me (or at least I think they are :p )

Programming is all about structure. You are handling a very complicated problem, so you need all the help you can get.
Creating structure in data is quite powerful, and that is what I am missing in your list (that is, all your solutions are 'one long list' where the place just varies a bit).

One long list of variables soon becomes unmanagable no matter where you put it. Merging 'related' data in a class is a useful solution, ie instead of

Code:
int mario_xpos;
int mario_ypos;

do

Code:
class Mario {
public:
  int xpos;
  int ypos;
}

Mario mario;
it adds a level of structure to your data, and thus reduces the number of variables at all levels, and reduces the number of parameters you need to pass as well.

In other words, making structure in your data is more important than the place where you keep the variables.


In general, you should end up with a small number of global variables (or in main).
There is not a single rule that fits all cases though.

I tend to make a global variable for each part, one for the display, one for graphics, one for the game world, one for 'things that move', etc.
I am not sure it is the right way; I do things differently at work, and I see other people also making other choices.
I can only say, just do wihat you believe is right, and don't be afraid to experiment or change it, if you think it will be better.
I have been programming many years, and I still change how I program every now and then (although the changes are quite small usually).

_________________
My project: Messing about in FreeRCT, dev blog, and IRC #freerct at oftc.net


Top
 Profile  
 
PostPosted: Mon Apr 09, 2012 5:51 pm 
Shake'n'Baker

Joined: Thu Dec 29, 2011 2:33 pm
Posts: 62
This forum is really great, even though it is for game developing,
beginner C++ questions are answered politely :)

I think I will try to put similar data to classes, like both of you mentioned.
Can't imagine why I didn't come up with that idea, since it is very logical*g*

And of course I should do some more experiments with pointers.
Today was okay, but they confuse me ever again*g*(no need to explain, there
is half an Internet full with it*g*).


Thank you much,
Aestond


Top
 Profile  
 
PostPosted: Mon Apr 09, 2012 7:30 pm 
Harmlessness does no harm
User avatar

Joined: Tue Sep 14, 2004 8:37 pm
Posts: 3808
Location: Ferriday, LA, US
aestond wrote:
This forum is really great, even though it is for game developing,
beginner C++ questions are answered politely :)

We all had to start somewhere. Unfortunately people on many support communities forget quickly just how difficult it can be to get somewhere from Square One. We're here to help. :)

aestond wrote:
And of course I should do some more experiments with pointers.
Today was okay, but they confuse me ever again*g*(no need to explain, there
is half an Internet full with it*g*).

Pointers are a pretty difficult concept for many to master, and the usual path to mastery usually involves a lot of bald spots. ;)

Might be an idea to invest in a proper, established book if you are very serious. The problem with Internet tutorials is that they cover things that have already been explained in much better ways (and it doesn't help that random Internet articles don't always mesh together well). For single, specialized tasks, an Internet article is fine in general. But, as far as learning a language in-and-out, I find that a good (emphasis on 'good') book is a HUGE help.

If you have a specific budget you would be willing to spend on a book, post back and someone will come back with recommendations. You can also swing by a place like Amazon.com and do a book search -- if something catches your eye, be sure to read the reviews (and filter out bogus reviews, such as those that give a book 1 star because "I have not received it" or 5 stars because "It arrived on time and in good condition" and such) when considering your purchase. There are lots of good books, but probably more bad books. :)

_________________
What most people don't understand about "enlightenment" is that it is not an end-goal; but where you find yourself just before taking a new "first step."


Top
 Profile  
 
PostPosted: Mon Apr 09, 2012 7:56 pm 
Shake'n'Baker

Joined: Thu Dec 29, 2011 2:33 pm
Posts: 62
I have some books :)
One about C, 2 about c++.
Don't remember the name of
2 of them now, but the one
I really spent alot of money for,
is this:
German version
English version

Of course I made some research before buying it(about 1 year ago) :)
The hint, learning from the book may be helpful, probably would have looked for pointers online.
I will try it by reading the book :) (also it smells better*g*)


Top
 Profile  
 
PostPosted: Tue Apr 10, 2012 7:09 am 
Harmlessness does no harm
User avatar

Joined: Tue Sep 14, 2004 8:37 pm
Posts: 3808
Location: Ferriday, LA, US
aestond wrote:
(also it smells better*g*)

I don't know about you, but I love the smell of dead tree in the morning. :) :D

_________________
What most people don't understand about "enlightenment" is that it is not an end-goal; but where you find yourself just before taking a new "first step."


Top
 Profile  
 
PostPosted: Thu Apr 12, 2012 5:18 pm 
Shake'n'Baker

Joined: Thu Dec 29, 2011 2:33 pm
Posts: 62
Will put some Code in here.
Trying to understand pointers as much as possible.
If I have a question, I'll post it in red color.
The code I post is for you, to understand my way of thinking, so my errors are reconstructable (! ;) ).

Code:
#include <iostream>

using namespace std;

void printit(int * i){  // expects a pointer as argument
   cout<<*i<<endl;      // the star deferences(?) the pointer and gives us what is located at the pointers address
   cout<<&i<<endl;      // & gives us the address. Same as in line 13, but this time, &i gives us the adress of the pointer(*i) itself
   cout<<i;             // gives us the address of i. Same as in line 16.
}

int main(){
    int anumber = 5;
    int * ptr_anumber = &anumber;  // with * initialized variables are pointers, holding an address.
                        //& before a variable, gives an address. The var the address is given to, must be of same type +
                        //pointer, e.g.: int * x = int &b; long * x = long &b //I know, syntax error ;)
    cout<<&anumber<<endl;
    printit(ptr_anumber);

return 0;
}


Top
 Profile  
 
PostPosted: Thu Apr 12, 2012 6:26 pm 
Dexterous Droid
User avatar

Joined: Wed Aug 18, 2004 7:40 pm
Posts: 3735
Location: South Africa
That looks right. Just "deferences" should be "dereferences" ;)

Quote:
e.g.: int * x = int &b; long * x = long &b //I know, syntax error ;)

int and long are the same thing. short is a short int (2 bytes). int is short hand for long int (4 bytes), and long is shorthand for the same thing. Damn, that sentence went down a long hill in a short amount of time.
Code:
    long a = INT_MAX;
    int b = a;
    cout << b << " and " << a << "\n\n\n";

output: 2147483647 and 2147483647

Quote:
The var the address is given to, must be of same type pointer

The exception to this rule is void* - void pointers can point to anything (and are dangerous because of this).

I changed your code a little because I wanted to point out one thing you may have missed, check ***. You do mention that it's the address of int* i, so maybe this isn't news to you. :) The LOG macro makes it a lot easier to read the output.
Code:
#include <iostream>
using namespace std;

#define LOG(x) cout << (#x) << " : " << (x) << endl
void printit(int * i){  // expects a pointer as argument
   LOG(*i);      // the star deferences(?) the pointer and gives us what is located at the pointers address
   LOG(&i);      // & gives us the address. Same as in line 13, but this time, &i gives us the adress of the pointer(*i) itself
   LOG(i);             // gives us the address of i. Same as in line 16.
}

int main(){
    int anumber = 5;
    int * ptr_anumber = &anumber;  // with * initialized variables are pointers, holding an address.
                        //& before a variable, gives an address. The var the address is given to, must be of same type +
                        //pointer, e.g.: int * x = int &b; long * x = long &b //I know, syntax error ;)
    LOG(anumber);
    LOG(&anumber);
    LOG(ptr_anumber);
    LOG(&ptr_anumber);
    printit(ptr_anumber);

return 0;
}


output:
anumber : 5
&anumber : 0x28ff44 <<--- this is the value of the pointer
ptr_anumber : 0x28ff44 <-|
&ptr_anumber : 0x28ff40 - the address of the pointer here ***
*i : 5
&i : 0x28ff20 - and over here are different *** because when you pass a parameter by value into a function, a copy is made for the function to operate with
i : 0x28ff44

_________________
Whatever the mind can conceive and believe, it can achieve


Top
 Profile  
 
PostPosted: Thu Apr 12, 2012 9:43 pm 
Shake'n'Baker

Joined: Thu Dec 29, 2011 2:33 pm
Posts: 62
Hey,
thank you :)
I am using #defines already, but never thought of doing it that way.
Quote:
Just "deferences" should be "dereferences"

That made me laugh*g* :doh

The int = long thing is strange.
Is it new? I have "learnt" the basic very int ago. ;)
That time, it was the same I would bet(and now I think, there is a possibility I could lose the bet*G*)

The whole pointer-stuff is really interesting. Accessing the ram directly if I understand it right.
That's the way, trainers(I think it's called trainers. The programs, you can cheat in games with) are
written, or?
I don't cheat, but writing a trainer some day would be nice *g*

Maybe C++ is bad:
I have one idea - mapeditor
I have one problem - pointer
I learn about pointers
I have much more ideas.
Will that ever stop? xDD

I have tried pointer with arrays, very easy.
Then I tried pointer with 2-dimensional arrays - tricky. Don't need help on that topic yet, I will come up with it
after reading a bit more :)


Edit:
Managed to play with pointers to a 2dimensional array of a class holding 2ints.
It's a very very ugly way, but it works.
In the next days, I will look up some better ways, those I found until now, look very strange to me.
Here what I've got:

Code:
//Now with array of classes

coord arraycoord[2][2];
arraycoord[0][0].x = 1;
arraycoord[0][1].x = 2;
arraycoord[1][0].x = 3;
arraycoord[1][1].x = 4;
arraycoord[0][0].y = 11;
arraycoord[0][1].y = 22;
arraycoord[1][0].y = 33;
arraycoord[1][1].y = 44;


coord * ptrarraycoord = &arraycoord[0][0]; //setting the pointer to the first array element
int temp;
temp = (*ptrarraycoord).x;
LOG(temp);
LOG(ptrarraycoord);
temp = (*(ptrarraycoord+1)).y;
LOG(temp);
//(...)
//going through every element one by one

LOG("change");
(*(ptrarraycoord+3)).y=555; //Changing the value of the last array element
temp= arraycoord[1][1].y;
LOG(temp);


Top
 Profile  
 
PostPosted: Fri Apr 13, 2012 5:57 pm 
Bytewise

Joined: Sun Oct 16, 2011 3:09 pm
Posts: 277
Location: Here (where else?)
aestond wrote:
The int = long thing is strange.
Is it new? I have "learnt" the basic very int ago. ;)
That time, it was the same I would bet(and now I think, there is a possibility I could lose the bet*G*)
It depends on the compiler, and your platform. The C standard (K&R) only says that a 'char' is a character (no size is listed), a 'short' is at least 16 bits, 'long' is at least 32 bits, and 'int' is at least as wide as a short and not longer than a long.

aestond wrote:
The whole pointer-stuff is really interesting. Accessing the ram directly if I understand it right.
Every statically allocated variable is in ram, the only difference is that the compiler finds you a nice place, so there is less things you can mess up :p

aestond wrote:
Maybe C++ is bad:
I have one idea - mapeditor
I have one problem - pointer
I learn about pointers
I have much more ideas.
Will that ever stop? xDD
Nope, it just gets worse.
I have around 10 things I want to do all the time, and don't have time enough for even just 1. The trick is to chose, and don't switch too often (as switching to a new subject costs time and you are not productive).

By the way, the real fun with pointers starts when you have pointers to pointers :p

aestond wrote:
Managed to play with pointers to a 2dimensional array of a class holding 2ints.
It's a very very ugly way, but it works.
There is a well-defined order of how values in an multi-dimensional array are laid out in memory, accessing them by pointer like you do is ok.

aestond wrote:
temp = (*ptrarraycoord).x;
You know 'ptrarraycoord->x' will work too, right?

aestond wrote:
temp = (*(ptrarraycoord+1)).y;
Moving the pointer make it easier:
Code:
coord *ptr = arraycoord[0];
for (unsigned int i = 0; i < sizeof(arraycoord)/sizeof(coord); i++) {
   printf("x=%d, y=%d\n", ptr->x, ptr->y);
   ptr++;
}
By the way, often, people have conventions to make reading code easier. Using all uppercase for #define names is one such convention. Another one is to make types like 'coord' different from normal variables. I tend to use CamelCase for classes/structs, and lower_letters for variables. It does not really matter what you use, but it makes code more readable if you make differences that way.

_________________
My project: Messing about in FreeRCT, dev blog, and IRC #freerct at oftc.net


Top
 Profile  
 
PostPosted: Fri Apr 13, 2012 6:32 pm 
Harmlessness does no harm
User avatar

Joined: Tue Sep 14, 2004 8:37 pm
Posts: 3808
Location: Ferriday, LA, US
Alberth wrote:
By the way, the real fun torture with pointers starts when you have pointers to pointers :p

Fixed that for you there. ;)

Alberth wrote:
By the way, often, people have conventions to make reading code easier. Using all uppercase for #define names is one such convention. Another one is to make types like 'coord' different from normal variables. I tend to use CamelCase for classes/structs, and lower_letters for variables. It does not really matter what you use, but it makes code more readable if you make differences that way.

For best results, take consistency into consideration when writing an application. If your project uses VARIABLE_NAME for defines; VariableName for constructs, _variableName for members fields, and variable_name for globals/temp variables, you should adhere to that convention strictly. After all, if you are away from your code for any length of time (or a third party is examining your code), this:

Code:
_x = calcX(destinationCoord.x, target_coord);
y = Calc_Y(DESTINATION_COORD.y, targetCoord);


Might be perfectly valid, working code -- but also highly confusing, working code. :)

_________________
What most people don't understand about "enlightenment" is that it is not an end-goal; but where you find yourself just before taking a new "first step."


Top
 Profile  
 
PostPosted: Sat Apr 14, 2012 6:03 pm 
Shake'n'Baker

Joined: Thu Dec 29, 2011 2:33 pm
Posts: 62
Thank you much, I will try your ideas
and yes, I should finally start using the
same writingtype for same kind of vars.

Probably won't be able to check here in
the next 5-6 days since I'm on Sardegna.

See you then :)


Top
 Profile  
 
PostPosted: Wed Apr 18, 2012 9:10 pm 
Shake'n'Baker

Joined: Thu Dec 29, 2011 2:33 pm
Posts: 62
I encountered another problem, I never had.

I think it has to do with heap and stack.
I got some buttons(it's a class) and some images I load.
Each button get's one image.
Usually I load buttons with:
Code:
sprite = SDL_LoadBMP("tiles.bmp"))

The buttons I call with:
Button * clickme = new Button();

But now it comes, that I have to initialize some buttons with Button clickme();

Why I have to do:
I a initialize all my buttons with new, the function, loading my images returns an error.
The strange thing:
1. Init SDL
2. load images
3. initialize buttons

The buttons don't have anything to do with the images. The only same is, that the buttons use the images as caption.

My idea: It's a problem with heap / stack.
But I am not sure, never got that far in a program*G*


Top
 Profile  
 
PostPosted: Thu Apr 19, 2012 3:03 am 
Bytewise

Joined: Sun Oct 16, 2011 3:09 pm
Posts: 277
Location: Here (where else?)
Your statement will not compile (number of parentheses is unbalanced), so you must use something else :p

Your order of doing things looks sane, I see no reason why it would fail.
The only thing I noticed was this (in the SDL documentation):

Code:
    /* Free the allocated BMP surface */
    SDL_FreeSurface(sprite);
If you do this, the sprite is no longer available, and using it will fail in unpredictable ways from here on.

If you don't do that, I think we need a more complete example, perhaps try to reproduce for one button?

_________________
My project: Messing about in FreeRCT, dev blog, and IRC #freerct at oftc.net


Top
 Profile  
 
PostPosted: Thu Apr 19, 2012 10:16 am 
Shake'n'Baker

Joined: Thu Dec 29, 2011 2:33 pm
Posts: 62
Thanks for your answere, but that is not the solution.

The code compiles without problems.
I can't free surfaces while the program runs, since I
need the images.

I have no time right now, later I will comment
the code and post the problematic line numbers,
so you could look at it yourself :)

Edit:
Strangely it works now.
I just renamed one of the images.
But still something wasn't right there, since the image name was absolutely correct!
Since this code just has to work, I am satisfied with that. But I think such a problem will come
again :|

At least I learned something about stack and heap and probably will try
to init almost everything into the heap!

In moments like this I understand, why people prefer other languages...
but I made my choice :)


Top
 Profile  
 
PostPosted: Thu Apr 19, 2012 6:51 pm 
Bytewise

Joined: Sun Oct 16, 2011 3:09 pm
Posts: 277
Location: Here (where else?)
aestond wrote:
Thanks for your answere, but that is not the solution.

The code compiles without problems.
:)
I already suspected that in your code you had nicely balanced parentheses :p



aestond wrote:
I can't free surfaces while the program runs, since I
need the images.
Indeed. It was a shot in the dark, but luckily you already took care of this potential problem.


aestond wrote:
Edit:
Strangely it works now.
I just renamed one of the images.
But still something wasn't right there, since the image name was absolutely correct!
Since this code just has to work, I am satisfied with that. But I think such a problem will come
again :|
It probably does. It sounds like you are relying on data that's living in free space, which is a dangerous place for data to exist.
Typical signals are what you experienced. Problems that come and go without doing any real fixing. The big puzzle is finding the thing that goes wrong. There are tools that can help you, for example valgrind, or by careful study of what the code does with respect to memory.

aestond wrote:
At least I learned something about stack and heap and probably will try
to init almost everything into the heap!
That does not help. It is not a pure stack problem nor a pure heap problem. You handle memory incorrectly, which will cause trouble at either place, except perhaps in a heap it will take longer before it causes crashes (since you have more heap than stack, and the usage patterns are different). Also, finding the cause of a problem in heap is near impossible.

The only way to get a reliable program is to understand how memory works, and use it in the right way.

My rule is that each piece of memory has a single owner, at all times it must be clear who owns what memory. Attached to ownership is the right to delete the memory. Obviously, the owner should only do that when the memory is not used any more.
By having a single owner, you eliminate cases where several objects think they should free the same memory (at different times), causing all kinds of nasty surprises later.

aestond wrote:
In moments like this I understand, why people prefer other languages...
Other languages may not be able to access free-ed memory, but they still have to deal with all other forms of chaos that can happen when several objects share the same memory, so you still have to have a picture of what memory is used by who.

_________________
My project: Messing about in FreeRCT, dev blog, and IRC #freerct at oftc.net


Top
 Profile  
 
PostPosted: Thu Apr 19, 2012 7:44 pm 
Shake'n'Baker

Joined: Thu Dec 29, 2011 2:33 pm
Posts: 62
I will try Valgrind and look up some more thinks about memory
management.

Right now I am rearranging my code. Putting classes belonging together in
outsourced files. That makes it so much easier to have a look at the code :)

It's gonna be a long weekend *g*

Quote:
My rule is that each piece of memory has a single owner, at all times it must be clear who owns what memory

Imagining you have 2 trees in your Code with the same sprite.
You just give them the adress of the sprite and not the whole image, do I understand it right?
That would be the way I do it.

Hope I understood it right.

Thank you,

Aestond


Top
 Profile  
 
PostPosted: Thu Apr 19, 2012 9:13 pm 
Dexterous Droid
User avatar

Joined: Wed Aug 18, 2004 7:40 pm
Posts: 3735
Location: South Africa
Rather don't load the same topic with new questions, create a new topic for each of your questions. It will make it much easier for people to search for information when they run into the same problems as you.

_________________
Whatever the mind can conceive and believe, it can achieve


Top
 Profile  
 
PostPosted: Fri Apr 20, 2012 5:13 pm 
Bytewise

Joined: Sun Oct 16, 2011 3:09 pm
Posts: 277
Location: Here (where else?)
aestond wrote:
Quote:
My rule is that each piece of memory has a single owner, at all times it must be clear who owns what memory
Imagining you have 2 trees in your Code with the same sprite.
You just give them the adress of the sprite and not the whole image, do I understand it right?
That would be the way I do it.
Yes, you want to share that memory between both users, to reduce memory use.

However, my point was, if you want to free all memory again afterwards, who should do the 'free' (or 'delete' if you used 'new')?

Both trees are equally fine, but you must 'free' it exactly one time (not 2 times and not 0 times). Also, you can only free the memory after establishing that the other user does not need it any more. How do you decide that?

In cases like above, I normally create a third object, that has ownership. It is responsible for 'free'-ing the memory at the end. Since it has the memory anyway, it can also act as the central point to query the address of the memory. It can also create the memory in the first place, and fill it with the sprite.

@IGTHORN: Sorry, but I didn't see a nice way to start a new topic, feel free to split the topic.

_________________
My project: Messing about in FreeRCT, dev blog, and IRC #freerct at oftc.net


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 24 posts ]  Go to page 1, 2  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group