Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

AppGameKit Classic Chat / Tier 2: I couldn't declare class outside app::loop

Author
Message
basjak
14
Years of Service
User Offline
Joined: 16th Apr 2010
Location: feel like signing up for mars
Posted: 20th Jun 2013 15:30 Edited at: 8th Jul 2013 10:11
hi:

so I created a class text and put it in a file called "class text imp.h":


and

created a variables files called variables.cpp:


and the main program in template.cpp:


now, I don't get any error when compiling on debug mode. but the program break when running. but, if I declare the "Text hello" within loop, the program run with no errors..

Attachments

Login to view attachments
Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 20th Jun 2013 16:21
For starters, take the spaces out of your file name. While many systems allow spaces in file names and directories, it is a very bad idea in writing code. Next, use the 'code' button instead of the 'quote' button for code inserts in your posts.

In my current WIP, I have over 50 classes defined in .h/.cpp file sets and there is no issue using any of them anywhere.

If you want to make a file with global variables, don't declare them as static. Just declare them as you want to use them. Then have a .h file (usually with the same name as the .cpp file) and add the declarations with the word 'extern' at the start of each line. And don't include any initializations. eg.
variables.h:

variables.cpp


Now, I don't know if using the class that way works. I would normally I would use a pointer in the header file (Text* hello and in the code file have it dynamically create the object (Text* hello = new Text("hello").

There is no need to store the char* value passed into the instantiation, unless you are going to use it to clean up, and you didn't. One of the things in Tier 2 that you need to be extremely conscious of is that anytime you use an AppGameKit function that returns a char* value, it is up to you to clean up the allocated space for that string using 'delete[] charvar;' (and the brackets are important since char* is treated as a char[]). But since you are passing in a constant string in your example, then you don't need to clean it up. But, if you plan to use the class more dynamically (taking input from some AppGameKit function), then you do want to clean it up.

I suspect that your main problem is using static in your variables.cpp file and not using a header with 'extern' declarations and including that in any other file that references the variables.

Cheers,
Ancient Lady
AGK Community Tester and AppGameKit Master
The Zoq2
15
Years of Service
User Offline
Joined: 4th Nov 2009
Location: Linköping, Sweden
Posted: 20th Jun 2013 16:57
Quote: "If you want to make a file with global variables, don't declare them as static. "


Is there a reason for that, I use static variables in my project without any issues (That I have seen so far)
JimHawkins
15
Years of Service
User Offline
Joined: 26th Jul 2009
Location: Hull - UK
Posted: 20th Jun 2013 17:08
You have to be VERY careful with static variables. They become, effectively, global even if inside a function.

See: http://msdn.microsoft.com/en-us/library/s1sb61xd(v=vs.80).aspx

-- Jim DO IT FASTER, EASIER AND BETTER WITH AppGameKit FOR PASCAL
basjak
14
Years of Service
User Offline
Joined: 16th Apr 2010
Location: feel like signing up for mars
Posted: 20th Jun 2013 17:46 Edited at: 20th Jun 2013 18:12
@ ancient lady:
about dynamic allocation, you're right. the help file did mention that returned strings are allocated dynamically. however, if you noticed in my case, there is no string stored in the class. THis what am trying to do at the moment, is to create my own classes and make sure are all clean so I can carry the main program without worrying about those technical stuff.
(thanks for reminding me.)

one more question!, I remember that deleting a dynamically allocated variable will live a bulky point in the memory. and I remember that plenty of deletes will slow down the program untill memory is full. correct?

about extern. that was my first attempt before i posted the second version with static. however, it is still not solved and i get the same type of error.

I have zipped the whole project, so please don't mind me disturbing you if you have time to look at it.

@The Zoq: try to use static variables only in functions that calling it again is relative to previous call.

Attachments

Login to view attachments
The Zoq2
15
Years of Service
User Offline
Joined: 4th Nov 2009
Location: Linköping, Sweden
Posted: 20th Jun 2013 18:45
Quote: "You have to be VERY careful with static variables. They become, effectively, global even if inside a function."


Hmm, but if I just use static variables for storing data which I use thruout the program, will I have a problem? Oh and sorry for sort of highjacking your thread
Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 20th Jun 2013 22:06 Edited at: 20th Jun 2013 22:11
Since the variables.cpp file was included in the main (template?) .cpp file, it would have created variables global to anything in that file and static would be fine (but totally unnecessary since it is in the same scope).

The idea behind using a .h/.cpp pair with 'extern' in the .h file is to make the variables in the .cpp file available to any other .cpp file, in the same project, that includes the header file. That is how to make something truly global within the compiled application.

'static' is very useful within functions and class method to make sure that a variable that is NOT a global one maintains its value between calls. If used in a function/class method, the scope for the variable is only that function/class method.

So, if you only really have one code file that uses a set of variables, declare them in that file. But by using a .cpp file in Visual Studio, it effectively gets compiled and linked in twice. The first time is as its own file and it gets added. Then again because it is included in another file. I'm actually surprised that this didn't cause a compile error, complaining about duplicate values.

As for dynamically creating and deleting stuff causing issues. You really only have an issue if you don't clean up after yourself. I did recognize that your example use of your class was using a constant string. If you assume that you will always use only a constant like that, there is absolutely no reason for your class to store the pointer. As a string constant it is taken care of by the standard stuff that hides behind everything (not AppGameKit, basic C/C++).

And, as long as you are consistent with your deletes, it does get cleaned up. Garbage collection is one of the things under the hood of every application. How effective it is depends on the platform. I have not seen frequent create/delete things causing issues in any well designed bit of code in all my years programming. And I've worked with some very complex systems. If you create a class that dynamically creates something, make sure it cleans it up in its constructor. Otherwise, you do get memory leaks.

I also just noticed that your header file ends with an "#endif". But there is no "#if<anything>" at the start. I assume that is just a copy/paste issue.

Now, I didn't mention it in my first post, but the way you are initialising txtno might not be a good idea, and it should not be defined as a const. This might be a better set of code for your class:


Note the following changes:
1. 'const int' changed to 'unsigned int'. The identifiers returned by all the create/load commands is of type 'UINT', which is unsigned int. And, while you are not changing the value, it is not a constant value and setting a constant value outside of its initial definition should not work.
2. changed 'char*' to 'const char*' in the constructor since that is what you are passing it and that is what you appear to want the input always to be. While compilers will allow mixing the types, they will also complain about it. Xcode always complains about type differences.
3. explicitly set txtno using the CreateText call instead of the inline initialisation (I don't know if that is how it is referred to, but I mean the ': txtno(agk::CreateText(any)' code. I suspect this would cause some issues. I wouldn't recommend using function calls as inline member initialisers. I'm not saying it can't be done, but I don't.
4. turned the input parameters for SetTextPosition to floats instead of ints. The actual agk::SetTextPosition command expects floating point values.

Cheers,
Ancient Lady
AGK Community Tester and AppGameKit Master
Hodgey
15
Years of Service
User Offline
Joined: 10th Oct 2009
Location: Australia
Posted: 21st Jun 2013 00:46
Quote: "if I declare the "Text hello" within loop, the program run with no errors."

I've actually had problems using the agk functions in places where they don't eventually end up inside one of the 3 app::begin, app::loop or app::end functions. One of the symptoms of such use was crashing. It doesn't seem to do it now (v1076) but if I create a sprite in a similar fashion to how you're creating text, it doesn't show up. However, if I move the createSprite() part to the app::begin method, it runs fine.

Quote: "Now, I don't know if using the class that way works. I would normally I would use a pointer in the header file (Text* hello and in the code file have it dynamically create the object (Text* hello = new Text("hello")"

AL's suggestion of this is probably the best way to do it. This is how I how I do it as well. I create global pointers which are initialised in app::begin() via the new keyword.

Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 21st Jun 2013 05:08
I hadn't thought of the issue of the initial constructor calling an AppGameKit function before the app::Begin() method had been called.

I suspect that is the biggest issue here (regardless of anything else I suggested).

Since I never had a class or other .cpp file that used any AppGameKit functions upon initial load, I had not run into that issue.

Now that I am aware of it, I can be sure not to do it in the future.

Cheers,
Ancient Lady
AGK Community Tester and AppGameKit Master
basjak
14
Years of Service
User Offline
Joined: 16th Apr 2010
Location: feel like signing up for mars
Posted: 21st Jun 2013 11:26
about enforcing char to const char, int to unsigned int. usually th visual studio mention that there possible loss of data, which is ok if you know that.

however

am even unable to declare the "Text hello" as global in app::begin().

back to the debugging, it is the command
that is unable to work. the break point on the debugging says it is on; cSprite.cpp.

there is nothing wrong with my code so far. it can't work somewhere and crash somewhere else. so this is something to do with AGK.

I tried all possibilities but, nothing has worked.

please if you can, download the Zip file and observe the code.

Attachments

Login to view attachments
Hodgey
15
Years of Service
User Offline
Joined: 10th Oct 2009
Location: Australia
Posted: 21st Jun 2013 12:15
Quote: "it can't work somewhere and crash somewhere else. so this is something to do with AGK. "

From my past experiences, I think it's best to for all agk functions to eventually get called in one of the app:: functions. You can have them in your class constructors, methods etc but those are most likely to work if called in begin, loop or end. With my latest project, I tried creating my Level object outside of those functions and no media showed up, just a few blank sprites. When I create it inside the app functions and it worked perfectly. I can't explain this but I'm happy to adhere to it.

basjak
14
Years of Service
User Offline
Joined: 16th Apr 2010
Location: feel like signing up for mars
Posted: 21st Jun 2013 12:39 Edited at: 21st Jun 2013 12:42
Quote: " I think it's best to for all agk functions to eventually get called in one of the app:: functions"


but that is not a flexible thing. then it's better to comeback to tier 1.

i wanted tier 2 for its flexibility.

at least if someone can correct my example or leave me with one of his examples.

Hodgey
15
Years of Service
User Offline
Joined: 10th Oct 2009
Location: Australia
Posted: 21st Jun 2013 14:09
Quote: "but that is not a flexible thing. "

I agree, it does make it more difficult. But my theory only has experimental backing, it could also be just the way I'm coding. We should ask Paul to be absolutely sure.

Quote: "i wanted tier 2 for its flexibility."

You still get a lot of flexibility. Let's not forget pointers and OOP.

Quote: "at least if someone can correct my example or leave me with one of his examples."

I gave your example a go but unfortunately I can't compile it. I'm running v1076 (Directx sdk doesn't want to install for me) and I'm guessing you're running one of the 108 betas?

The way I'd do it is something like this. In your header file, you'd create a pointer e.g


And then in the app::begin method you'd have this


I've just realized you don't have a default constructor. The constants are also a bit of a road bump for dynamic allocation. Maybe experiment with placement new (I've only just learned of it).

And then remember to free it in app::end().

That's how I'm doing it currently.

Example from project I'm working on.


JimHawkins
15
Years of Service
User Offline
Joined: 26th Jul 2009
Location: Hull - UK
Posted: 21st Jun 2013 14:11
I don't know if it's the same in C++, but in Pascal the AppGameKit engine is NOT started until the Begin method is called. Consequently, calling anything AppGameKit before the Begin method will have highly unpredictable results.

-- Jim DO IT FASTER, EASIER AND BETTER WITH AppGameKit FOR PASCAL
Hodgey
15
Years of Service
User Offline
Joined: 10th Oct 2009
Location: Australia
Posted: 21st Jun 2013 14:17
I just had a quick peep at the core.cpp. It calls agk::InitGL() with the comment "initialize graphics api" right before the app::Begin call. So it would seem you're correct Jim, at least on the graphics side of things.

basjak
14
Years of Service
User Offline
Joined: 16th Apr 2010
Location: feel like signing up for mars
Posted: 21st Jun 2013 14:59 Edited at: 21st Jun 2013 15:00
@ancient lady:
thank you, you gave me the hint to get back to using pointer. putting pointer name before app::begin is still not flexible thing for large programs(it's ok for small apps).

the only solution i managed to do is to declare a static pointer to class Text at the variable.h files and then name it at app::begin. this way will not have to create it at app::loop.

buy the way that was the only solution exist after plenty of work. (extern will not solve the problem.)

thank you ancient_lady, The Zoq2, JimHawkins, Hodgey. I don't know why no one came up with such a problem in the forum.

Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 21st Jun 2013 17:07
You can create many files with classes and variables and class pointers (like I said, I have over 50) and include them in your project.

The only inflexibility is that, if you want your class to use an AppGameKit function, you cannot have something like your original code that calls CreateText before the app::Begin method has been started.

It is a simple thing to have a header file with the word 'extern' to indicate that the variable is declared in another file and then include the header instead of the .cpp file (which is simply not done in proper C++ programming). To include information from another .cpp file in a different .cpp file, you use .h (or .hpp) header files to include the definition of what is in the other file.

If you understand proper OOP and C/C++, you are open to lots of great stuff.

Because of the way that AppGameKit interacts with the different platforms to collect user/device inputs (mouse movement, touches, clicks, accelerometers, etc.) there is one big inconvenience in Tier 2. The user/device inputs are collected only once before or after (not sure which) each app::Loop method execution.

The result of this is that you cannot do something like:


While your display would update if you made any changes in that loop, you will never get a pointer press.

In Tier 2 it is necessary to create state engine type stuff to handle some interactions.

The physics and display will update any time you call agk::Sync(). So you can do lots of things to update or change. But you will not get changes in pointers or text input or accelerometer values until the end/beginning of the app::Loop() call.

I do plan to create a simple example of Tier 2 state engine that shows how to handle menu processing and http processing. I just have to find the time.

And managing my time is why I really try to avoid actually looking at uploaded projects. I have to spend time to make sure that they work in my environment and then go through code and such and I am not paid to do any of this. And I have my own projects to take care of, as well as whatever needs my business has. I actually spend more time trying to help in this forum than I should.

Cheers,
Ancient Lady
AGK Community Tester and AppGameKit Master
XanthorXIII
AGK Gold Backer
13
Years of Service
User Offline
Joined: 13th May 2011
Location:
Posted: 21st Jun 2013 19:30
Here is an excellent article. Ignore the SDL stuff but look at the classes and statemachine for this.
http://lazyfoo.net/articles/article06/index.php
Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 21st Jun 2013 20:03
Ahhh! I remember that stuff well.

My example was going to be more along the lines of switch/case, for simplicity.

Now you have me thinking about expanding my classes to properly do the state machine bits.

I actually have multiple little state machines for different bits. Some are within classes and some not.

But if I started trying to make it completely OOD/P, my hubby might loose patience. I just told him that I finally have everything working (including the level editor) and only need to finish my levels and I will be ready to publish. Starting a major over-design might be too much right now. Converting it from Tier 1 to Tier 2 for starters took a month (because of then making the decision to turn all the processes into classes and then dealing with making proper state processing and such).

My current and ex and many an employer and fellow employers have observed that it is too easy to get past 'good enough and working' while trying to make it 'really perfect'.

Cheers,
Ancient Lady
AGK Community Tester and AppGameKit Master
basjak
14
Years of Service
User Offline
Joined: 16th Apr 2010
Location: feel like signing up for mars
Posted: 21st Jun 2013 20:04
@ancient lady.

Quote: "If you understand proper OOP and C/C++, you are open to lots of great stuff."

I belong to old C++ school and last time I made big C++ project was between 2005 - 2007.
the good thing is I kept my references since that time so actually I found myself up and ready as I know c++ yesterday.

but we can (possibly, I haven't tried yet.) create multiple loops such as:

App app;
App level1;
App level2;
...
..
.

this way we can have multiple sub loops.

I left my computer at work so I can't tell you the result until Monday.

one last question:
if I prepare my claases on visual C++. do I have to consider many changes in other platforms. what I mean do other platforms use libraries such as string, vector, .......

Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 21st Jun 2013 20:31 Edited at: 21st Jun 2013 20:35
I didn't mean to imply a lack of knowledge, just an observation. My apologies.

I am 100% certain that you CANNOT make multiple loops by declaring multiple App things. (If this is not the case, let one of the AppGameKit developers speak up.)

If you look at the template.h file, it has the line 'extern app App;' near the end. This is declaring an external instantiation of the app class just defined in template.h.

If you then look in the various platform specific files, you will find that App is used everywhere to control it (calls to App.Begin() and App.End() and App.Loop()).

Somewhere under the hood in a library is the actual instantiation 'app App;' line. This varies by platform.

You cannot call the app Begin/Loop/End methods yourself to do things because they need to happen within the proper context of initializing the display, cleaning it up, updating it and handling user/device/external interactions.

The AppGameKit engine controls your universe. You just tell it what you want it to do.

Now, as long as you use totally standard C++ and stay away from platform specific stuff, the exact same files work in all platforms.

There are only a small handful of things I do to accommodate different platforms. My code set includes 43 .cpp files and about 44 .h (one is for the few constants needed by more than one file). And I use all of them in all the platforms I have (Windows, Mac/iOS and Android) without a single problem.

The only annoying thing in Android is that the cygwin compiler doesn't do C++11 which supports the map class (hash thing). I had found an Android NDK version that would compile, but it then crashed on the Android devices, much to my disappointment.

But, std::vector and std::list work fine. As does std::string (I like std::string).

In template.h (I leave WINDOW_TITLE out of the #ifdef because I actually use it in a place other than where AppGameKit expects it for Windows and Mac):


The most recent templates did not have 'AGKWINDOWS' defined in the preprocessor section, unlike earlier ones. But is easy to add.

One of the methods I add to app is 'closeThisApp'. It has a series of #ifdef's, one for each platform, that defines the proper way to force the app to exit for that platform (even if we are not supposed to have an exit button for iOS or Android, which I will have).

Cheers,
Ancient Lady
AGK Community Tester and AppGameKit Master
Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 21st Jun 2013 20:36
This is my closeApp method (stripped of some stuff, but enough to force closing the app, should only be called AFTER all cleanups):


Cheers,
Ancient Lady
AGK Community Tester and AppGameKit Master

Login to post a reply

Server time is: 2024-11-24 15:30:12
Your offset time is: 2024-11-24 15:30:12