C++ Projektit / Esimerkki koodit
Re: C++ Projektit / Esimerkki koodit
Kiitos avusta. Muuten pitääkö olla linkattuna jotain toisia linkkejä linkittää projektiin kuin(mingw32, SDLmain, SDL), jotta saisin joko cout:la tai printf:ä edes jotain infoa ulos mitä tapahtuu pelin muuttujapuolella. Nimittäin tällä hetkellä ne eivät kirjoita mitään. Vaikka on iostream includettu.. (Sitä tuskin vissiin edes tarvii..?)
Solar Eclipse
We're in a simulation, and God is trying to debug us.
Re: C++ Projektit / Esimerkki koodit
SDL tekee standardivirtojen kanssa kepposet: se ohjaa virrat tiedostoihin. Ts. int main(int argc, char ** argv); ei ole ohjelman oikea main() funktio koska 'main' on määriteltu esikääntäjän makroksi SDL.h:ssa, joka taas tekee omia säätöjään ennenkuin antaa kontrollin tälle vale-main()ille. (mm. debuggaus ei onnistu ellei SDL_init():lle anna "paracute" flagia)MaGetzUb wrote:Kiitos avusta. Muuten pitääkö olla linkattuna jotain toisia linkkejä linkittää projektiin kuin(mingw32, SDLmain, SDL), jotta saisin joko cout:la tai printf:ä edes jotain infoa ulos mitä tapahtuu pelin muuttujapuolella. Nimittäin tällä hetkellä ne eivät kirjoita mitään. Vaikka on iostream includettu.. (Sitä tuskin vissiin edes tarvii..?)
Ongelma ratkeaa joko ohjaamalla toisen kerran virrat takaisin konsoliin, tai kiertämällä SDL:n entrypoint härpäkkeet:
#include <SDL/SDL.h> // SDL:n headerin includetus.
#undef main // poista SDL:n headerin makro pasta, joka uudelleen määrittelee 'main' nimen. (Eli main():isi ei ollutkan 'main', vaan jokin muu makron määräämä nimi, jota oikea main() kutsui jostain SDL:n syövereistä.)
#include <iostream>:n tarvii aina jos käytät tiedostossa cout:ia tai cin:iä, koska eihän muuten kääntäjä tiedä mitä cout ja cin meinaavat. Note: C++:ssa C-kielen headerit sisällytetään muodossa #include <c[C-standardikirjason_header_nimi_ilman .h päätettä]> Esim. "#include <cstdio>" printf():ää varten.
Last edited by JATothrim on Thu Jul 07, 2011 6:42 am, edited 1 time in total.
-On selkeästi impulsiivinen koodaaja joka...
Re: C++ Projektit / Esimerkki koodit
Eli siis mitä ymmärsin tuosta viestistäsi, minun pitää siis kutsua #include <SDL.h>:n jälkeen undef main? Ja Enköhän ole oikein nuo kirjastot hoitanut:
Sisälsikös cstdlib Rand() -funktion?
Code: Select all
#include <iostream>
#include <cmath>
#include <string>
#include <cstdlib>
#include <sstream>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <SDL/SDL_ttf.h>
#include <SDL/SDL_mixer.h>
#include <SDL/SDL_rotozoom.h>
//Ja tähän kohtaan: undef?
#undef main
//^ noin? :P
#define PI 3.141592653589793
Eli siis SDL_Init(SDL_INIT_EVERYTHING|PARAC[H]UTE?);JAtothrim wrote: mm. debuggaus ei onnistu ellei SDL_init():lle anna "paracute" flagia)
Solar Eclipse
We're in a simulation, and God is trying to debug us.
Re: C++ Projektit / Esimerkki koodit
SFML on kyllä SDL:n verrattuna paljon parempi eikä siinä muistaakseni ollut tuommoisia tyhmä turhia lisäkikkailuita vaadittuna, että jotain näkyy konsoli-ikkunassakin. Se on lisäksi helppokäyttöisempi joten suosittelen siihen tutustumista jos vaan mahdollista (eli siis et ole tekemässä jotain valtavaa projektia jo SDL:llä ja SFML:ään vaihto olis vaan tyhmää kesken kaiken).
Re: C++ Projektit / Esimerkki koodit
Joo ei mulla ollu tarkoitus muutaku tehä luokat kuville ja äänille. SDL:ä, et niitä voi sitten käyttää myöhemmissä projekteissa. Pitääpä tutustua tuohon SFML:n.. Näytti aika mielenkiintoiselta..temu92 wrote:SFML on kyllä SDL:n verrattuna paljon parempi eikä siinä muistaakseni ollut tuommoisia tyhmä turhia lisäkikkailuita vaadittuna, että jotain näkyy konsoli-ikkunassakin. Se on lisäksi helppokäyttöisempi joten suosittelen siihen tutustumista jos vaan mahdollista (eli siis et ole tekemässä jotain valtavaa projektia jo SDL:llä ja SFML:ään vaihto olis vaan tyhmää kesken kaiken).
Solar Eclipse
We're in a simulation, and God is trying to debug us.
Re: C++ Projektit / Esimerkki koodit
Yksi viimeisimpiä asitoita jonka opettelin C++:sta oli pointer-to-member-function konsepti. Menetelmällä käytännössä voidaan poistaa tietystä paikkaa koodista helposti if- ja switch-rakenteita, tai ajaa samaa jäsen funktiota usealle eri oliolle.
Lisää (ja parempaa) tietoa http://www.parashift.com/c++-faq-lite/p ... mbers.html sivuilta.
Code: Select all
class DoStuff
{
public:
void stuff1();
void stuff2();
void strufN();
//typedeffi on kätevä:
typedef void (DoStuff::*ptrtomemberfn)();
ptrtomemberfn selectedfunc;
};
DoStuff doit1, doit2;
doit1.selectedfunc = &DoStuff::stuff1; // asetetaan "pointteri" jäsen funktioon.
(doit2 .* doit1.selectedfunc)(); //kutsuu DoStuff::stuff1 jäsen funktiota [i]doit2 oliolla[/i].
-On selkeästi impulsiivinen koodaaja joka...
Re: C++ Projektit / Esimerkki koodit
Muutamia funktioita geometriaan:
(vaatii cmath kirjaston sisällytettynä ja PI määrityksen)
Funktiot:
(vaatii cmath kirjaston sisällytettynä ja PI määrityksen)
Code: Select all
#include <cmath>
#define PI 3.141592653589793
Code: Select all
double cos2(double deg){return cos(wrapangle(deg)*PI/180);}
double sin2(double deg){return sin(wrapangle(deg)*PI/180);}
double getangle(double x,double y, double x2, double y2){
double vecunX = x-x2;
double vecunY = y-y2;
double atn = atan2(vecunY, vecunX);
if (x2>=x && y2 < y) {
return 90-(abs(atn)*180/PI-90);
}else if(x2 < x && y2<=y){
return 180.0-(atn)*180/PI;
}else if(x2<x && y2>=y){
return 180.0+abs(atn)*180/PI;
}else if(x2>=x && y2>y){
return wrapangle(270-(90-abs(atn)*180/PI));
}
return 0;
}
double distance(double x,double y, double x2, double y2){
return pow((x2-x)*(x2-x)+(y2-y)*(y2-y), 0.5);
}
double wrapangle(double angle){
if(angle<0){
return 360-(fmod(abs(angle), 360.0));
}
return fmod(angle, 360.0);
}
Solar Eclipse
We're in a simulation, and God is trying to debug us.
Re: C++ Projektit / Esimerkki koodit
Why would you even do that, son?MaGetzUb wrote:Muutamia funktioita geometriaan:
(vaatii cmath kirjaston sisällytettynä ja PI määrityksen)Funktiot:Code: Select all
#include <cmath> #define PI 3.141592653589793
Code: Select all
double cos2(double deg){return cos(wrapangle(deg)*PI/180);} double sin2(double deg){return sin(wrapangle(deg)*PI/180);} double getangle(double x,double y, double x2, double y2){ double vecunX = x-x2; double vecunY = y-y2; double atn = atan2(vecunY, vecunX); if (x2>=x && y2 < y) { return 90-(abs(atn)*180/PI-90); }else if(x2 < x && y2<=y){ return 180.0-(atn)*180/PI; }else if(x2<x && y2>=y){ return 180.0+abs(atn)*180/PI; }else if(x2>=x && y2>y){ return wrapangle(270-(90-abs(atn)*180/PI)); } return 0; } double distance(double x,double y, double x2, double y2){ return pow((x2-x)*(x2-x)+(y2-y)*(y2-y), 0.5); } double wrapangle(double angle){ if(angle<0){ return 360-(fmod(abs(angle), 360.0)); } return fmod(angle, 360.0); }
Tuon pitäisi olla korkeintaan makro :<
EDIT:
miksei ole omassa nimiavaruudessa?
Re: C++ Projektit / Esimerkki koodit
Miksi pitäisi olla omassa nimiavaruudessa? Ja makroihin en ole tutustunut, niin näin oletin nuo funktiot olevan tarpeeksi käteviä.esa94 wrote:Why would you even do that, son?MaGetzUb wrote:Muutamia funktioita geometriaan:
(vaatii cmath kirjaston sisällytettynä ja PI määrityksen)Funktiot:Code: Select all
#include <cmath> #define PI 3.141592653589793
Code: Select all
double cos2(double deg){return cos(wrapangle(deg)*PI/180);} double sin2(double deg){return sin(wrapangle(deg)*PI/180);} double getangle(double x,double y, double x2, double y2){ double vecunX = x-x2; double vecunY = y-y2; double atn = atan2(vecunY, vecunX); if (x2>=x && y2 < y) { return 90-(abs(atn)*180/PI-90); }else if(x2 < x && y2<=y){ return 180.0-(atn)*180/PI; }else if(x2<x && y2>=y){ return 180.0+abs(atn)*180/PI; }else if(x2>=x && y2>y){ return wrapangle(270-(90-abs(atn)*180/PI)); } return 0; } double distance(double x,double y, double x2, double y2){ return pow((x2-x)*(x2-x)+(y2-y)*(y2-y), 0.5); } double wrapangle(double angle){ if(angle<0){ return 360-(fmod(abs(angle), 360.0)); } return fmod(angle, 360.0); }
Tuon pitäisi olla korkeintaan makro :<
EDIT:miksei ole omassa nimiavaruudessa?
Solar Eclipse
We're in a simulation, and God is trying to debug us.
Re: C++ Projektit / Esimerkki koodit
Kaikki C++ oppaat: Macros are evil. Oikeasti, makrot on saatu C++:aan perintönä C-kielestä, jossa niiden käyttö oli vaivatonta ja ellei jopa suositeltavaa. Jos meinaat C++:aa kirjoittaessa tehdä makron, ollaan jo hakoteillä, koska C++:n inline funktio ajaa asian monta kertaa paremmin. Funkkarista voidaan tehdä vieläpä suoraan template versio, jolloin ei tarvita naputellla erikseen double ja float versioita. :>MaGetzUb wrote:Miksi pitäisi olla omassa nimiavaruudessa? Ja makroihin en ole tutustunut, niin näin oletin nuo funktiot olevan tarpeeksi käteviä.esa94 wrote:Why would you even do that, son?MaGetzUb wrote:Muutamia funktioita geometriaan:
(vaatii cmath kirjaston sisällytettynä ja PI määrityksen)Funktiot:Code: Select all
#include <cmath> #define PI 3.141592653589793
Code: Select all
double cos2(double deg){return cos(wrapangle(deg)*PI/180);} double sin2(double deg){return sin(wrapangle(deg)*PI/180);} double getangle(double x,double y, double x2, double y2){ double vecunX = x-x2; double vecunY = y-y2; double atn = atan2(vecunY, vecunX); if (x2>=x && y2 < y) { return 90-(abs(atn)*180/PI-90); }else if(x2 < x && y2<=y){ return 180.0-(atn)*180/PI; }else if(x2<x && y2>=y){ return 180.0+abs(atn)*180/PI; }else if(x2>=x && y2>y){ return wrapangle(270-(90-abs(atn)*180/PI)); } return 0; } double distance(double x,double y, double x2, double y2){ return pow((x2-x)*(x2-x)+(y2-y)*(y2-y), 0.5); } double wrapangle(double angle){ if(angle<0){ return 360-(fmod(abs(angle), 360.0)); } return fmod(angle, 360.0); }
Tuon pitäisi olla korkeintaan makro :<
EDIT:miksei ole omassa nimiavaruudessa?
Vinkki vinkki note note: cmath:ssa on PI vakio valmiina: M_PI, ja tästä puolikas M_PI_2, etc.
EDIT: niin tänks wrapanglesta. :]
-On selkeästi impulsiivinen koodaaja joka...
Re: C++ Projektit / Esimerkki koodit
Riippuu kääntäjästä löytyykö M_PI vai ei. Ainakaan Visual C++ 2010 ei tunnista sitä. Aika ihmeellistä kyllä, ettei se kuulu standardiin. http://cboard.cprogramming.com/cplusplu ... -m_pi.html. Koodi toimii siis useammissa kääntäjissä, jos sen vakion määrittelee itse.JATothrim wrote: Kaikki C++ oppaat: Macros are evil. Oikeasti, makrot on saatu C++:aan perintönä C-kielestä, jossa niiden käyttö oli vaivatonta ja ellei jopa suositeltavaa. Jos meinaat C++:aa kirjoittaessa tehdä makron, ollaan jo hakoteillä, koska C++:n inline funktio ajaa asian monta kertaa paremmin. Funkkarista voidaan tehdä vieläpä suoraan template versio, jolloin ei tarvita naputellla erikseen double ja float versioita. :>
Vinkki vinkki note note: cmath:ssa on PI vakio valmiina: M_PI, ja tästä puolikas M_PI_2, etc.
EDIT: niin tänks wrapanglesta. :]
Eikös inline ole muuten vain vihje kääntäjälle? Kääntäjän ei siis ole pakko optimoida sitä funktio kutsua pois vaikka funktio olisi inline.
@Esa94:
Ei paria tuollaista funktiota tarvitse välttämättä omaan nimiavaruuteensa laittaa. Hankaloittaa vain käyttämistä.
@MaGetzUb:
Mitä sen getangle-funktion on tarkoitus tehdä? Palauttaa minkä kahden välinen kulma?
Re: C++ Projektit / Esimerkki koodit
Kaikkien funktioiden kuuluisi olla omissa käyttötarkoituksen tai kirjaston mukaisissa nimiavaruuksissaan. Se ei myöskään vaikeuta käyttämistä lainkaan. Miksi luulit että using-lause on ylipäätään olemassa? Onko standardikirjaston funktioita, olioita ja luokkia mielestäsi jotenkin hankala käyttää kun ne ovat omassa nimiavaruudessaan?
JATothrim: Perehdy C1X:n geneerisiin makroihin. Ajavat saman asian kuin ylikuormittaminen.
Joissain tapauksissa makrojen käyttöä ei voi välttää, sillä malleja ei vain voi aina raiskata miten haluaa. Arvojen antaminen niille on kuitenkin ihan kätevä tapa luoda asioita (Esimerkiksi jos luokan jäsenen koko riippuu malliparametrista, voidaan sille antaa jokin numero kätevästi käännöksen yhteydessä)
Implisiittisen tyyppimuunnoksen takia float-versioita funktioista jotka vain muuntavat arvoja cmathin funktioille ei kannata tehdä. Tyyppi joudutaan kuitenkin yhä muuntamaan takaisin doubleksi.
math.h:n vakiot eivät ole standardissa mutta _GNU_SOURCE tai _USE_MATH_DEFINES (riippuen kääntäjästä) korjaa sen asian. En muista tukeeko clang niitä lainkaan, mutta todennäköisesti se hyväksyy GNU:n vivun.
C++–opas ei ole absoluuttinen auktoriteetti. Ei gotoonkaan kuole.
JATothrim: Perehdy C1X:n geneerisiin makroihin. Ajavat saman asian kuin ylikuormittaminen.
Joissain tapauksissa makrojen käyttöä ei voi välttää, sillä malleja ei vain voi aina raiskata miten haluaa. Arvojen antaminen niille on kuitenkin ihan kätevä tapa luoda asioita (Esimerkiksi jos luokan jäsenen koko riippuu malliparametrista, voidaan sille antaa jokin numero kätevästi käännöksen yhteydessä)
Implisiittisen tyyppimuunnoksen takia float-versioita funktioista jotka vain muuntavat arvoja cmathin funktioille ei kannata tehdä. Tyyppi joudutaan kuitenkin yhä muuntamaan takaisin doubleksi.
math.h:n vakiot eivät ole standardissa mutta _GNU_SOURCE tai _USE_MATH_DEFINES (riippuen kääntäjästä) korjaa sen asian. En muista tukeeko clang niitä lainkaan, mutta todennäköisesti se hyväksyy GNU:n vivun.
C++–opas ei ole absoluuttinen auktoriteetti. Ei gotoonkaan kuole.
Re: C++ Projektit / Esimerkki koodit
Juu, eipä mitään. Tuon wrapanglen kanssa sai oikeasi pähkäilläkkin hetkenaikaa, et miten sen kannattaisi toteuttaa, loppujenlopuksi se se olikin aika yksinkertaista.JATothrim wrote: EDIT: niin tänks wrapanglesta. :]
Siis se toimii samalla lailla, kuin CoolBasic:n Getangle. Eli se palauttaa kahden koordinaatin välisen kulman.Dimple wrote:@MaGetzUb:
Mitä sen getangle-funktion on tarkoitus tehdä? Palauttaa minkä kahden välinen kulma?
Solar Eclipse
We're in a simulation, and God is trying to debug us.
Re: C++ Projektit / Esimerkki koodit
Mikä idea on laittaa kaikki funktiot nimiavaruuteen vain "koska niin kuuluu tehdä"? Kyllä mielestäni pitää jokin syy olla siihen, että jotain ominaisuutta käytetään. Jokin muu syy kuin se, että jollain foorumille kirjoittelevalla on jumaluuskompleksi.
Nimiavaruudet keksittiin siksi, että eri kirjastoissa voisi olla saman nimisiä funktioita ilman, että se aiheuttaisi ongelmia, kun molempia kirjastoja halutaan käyttää samassa ohjelmassa. Ratkaisu on toimiva, ja kirjastoissa on hyvä tapa käyttää nimiavaruuksia, vaikka on ilman niitäkin pärjätty (esim. C:n kirjastot).
Mutta mitä hyötyä on tehdä näin?
Tuossahan menetetään kaikki nimiavaruudesta saatava hyöty. Hieman parempi olisi tehdä näin:
Mutta edelleen, jos joku toinenkin kirjasto käyttää "func"-nimistä funktiota, ollaan ongelmissa. Paras tapa olisi tehdä näin:
Tämä on myös se tapa, mitä itse käytän, mutta se hankaloittaa funktioiden käyttämistä, kun jokaisen kutsun eteen pitää kirjoittaa se nimiavaruus. Vaikka käyttäisi using-sanaa, täytyy se kuitenkin aina muistaa laittaa sinne. Jos käyttää sitä jokaiselle funktiolle erikseen, täytyy se myös muistaa laittaa jokaiselle erikseen. Vähänkään isommissa kirjastoissa nimiavaruutta kannattaa ehdottomasti käyttää, mutta mielestäni muutaman funktion kanssa se vain hankaloittaa asioita. Lisäksi nimiavaruuden käyttäminen sitoo kirjaston C++:an vaikka muu koodi olisikin C yhteensopivaa.
@MaGetzUb:
Eli tekeekö tämä saman asian? Onko sinun koodissasi positiivinen kulma toiseen suuntaan?
Nimiavaruudet keksittiin siksi, että eri kirjastoissa voisi olla saman nimisiä funktioita ilman, että se aiheuttaisi ongelmia, kun molempia kirjastoja halutaan käyttää samassa ohjelmassa. Ratkaisu on toimiva, ja kirjastoissa on hyvä tapa käyttää nimiavaruuksia, vaikka on ilman niitäkin pärjätty (esim. C:n kirjastot).
Mutta mitä hyötyä on tehdä näin?
Code: Select all
namespace NameSpace {
void func() {}
}
using namespace NameSpace;
int main() {
func();
return 0;
}
Code: Select all
namespace NameSpace {
void func() {}
}
using NameSpace::func;
int main() {
func();
return 0;
}
Code: Select all
namespace NameSpace {
void func() {}
}
int main() {
NameSpace::func();
return 0;
}
Tuo on kyllä puhdasta potaskaa. Jos pitää muistaa enemmän asioita kun käyttää niitä funktioita, silloin niitä on hankalampi käyttää.esa94 wrote: Kaikkien funktioiden kuuluisi olla omissa käyttötarkoituksen tai kirjaston mukaisissa nimiavaruuksissaan. Se ei myöskään vaikeuta käyttämistä lainkaan.
@MaGetzUb:
Eli tekeekö tämä saman asian? Onko sinun koodissasi positiivinen kulma toiseen suuntaan?
Code: Select all
#include <cmath>
#include <cstdio>
#define PI 3.14159
// Strukti, joka tallentaa vektorin
struct Vect2D {
Vect2D(double newX, double newY) { x = newX; y = newY; }
double x;
double y;
};
// Laskee kahden vektorin välisen pistetulon
double dot(Vect2D vect1, Vect2D vect2) {
return vect1.x*vect2.x + vect1.y*vect2.y;
}
// Laskee vektorin suuruuden (tai pituuden, miten tykkää)
double magnitude(Vect2D vect) {
return sqrt(pow(vect.x, 2) + pow(vect.y, 2));
}
// Laskee kahden pisteen välisen kulman käyttäen pistetulon määritelmää ( dot(a,b) = |a||b| * cos phi <=> phi = acos(dot(a,b) / (|a||b|)) )
double getAngle(double x, double y, double x2, double y2) {
// Tämä tarkistus estää sen, että jaettaisiin nollalla.
// Käytännössä virheentarkistus kannattaisi toteuttaa paremmin, mutta funktion pysäyttäminen
// saa nyt luvan riittää. :)
if(x2-x == 0 && y2-y == 0)
return 0;
// Muodostetaan vektorit.
Vect2D vect(x2-x, y2-y);
Vect2D vect2(1, 0);
// Lasketaan vektoreiden välinen kulma.
double angle = acos(dot(vect, vect2) / (magnitude(vect)*1) );
// Palautetaan joko kulma tai sen käänteisluku. Ilman tätä funktio palauttaisi saman kulman
// pisteille (0,0)->(1,1) ja (0,0)->(1,-1).
if(vect.y >= 0)
return angle;
else
return -angle;
}
// Oma toteutukseni WrapAnglelle, joka on helppo muistaa ja toteuttaa lennossa.
double wrapAngle(double angle) {
while(angle > 360)
angle -= 360;
while(angle < 0)
angle += 360;
return angle;
}
int main() {
printf("getAngle-testi: %f", wrapAngle(getAngle(0, 0, 1, -1) / PI * 180)); // Pitäisi palauttaa 315 (eli getAngle palauttaa -45 astetta)
printf("\nwrapAngle-testi: %f", wrapAngle(1445)); // Pitäisi palauttaa 5
printf("\nwrapAngle-testi: %f", wrapAngle(-1445)); // Pitäisi palauttaa 355
getchar();
return 0;
}
-
- Moderator
- Posts: 1583
- Joined: Mon Aug 27, 2007 11:24 pm
- Location: Otaniemi - Mikkeli -pendelöinti
Re: C++ Projektit / Esimerkki koodit
using on siitä näppärä avainsana, että saa itse määrätä mitä nimiavaruuksia käytetään - eli jos kutsutaan kirjasto::funktio -nimistä funktiota hyvin usein, nimeä voi lyhentää. Toisaalta, jos myös nimiavaruus kirjasto2 sisältää funktion nimeltä funktio, jota ei kutsuta laajan ohjelman aikana kuin kerran, ei tarvitse alkaa kikkailla uudelleennimeämisten kanssa vaan voi kutsua yksinkertaisesti kirjasto2::funktio().
Itse en ylipäänsäkään juuri nimiavaruuksia käyttele. Kun pitää luokkiensa nimet ristiriidattomina niin niissä voi vaikka jokaisessa olla metodi luokka::metodi :)
Itse en ylipäänsäkään juuri nimiavaruuksia käyttele. Kun pitää luokkiensa nimet ristiriidattomina niin niissä voi vaikka jokaisessa olla metodi luokka::metodi :)
Re: C++ Projektit / Esimerkki koodit
Ei tokikaan, sillä käytössäsi on todennäköisesti ainakin muutama kirjasto jotka määrittelevät omat funktionsa ja mahdollisesti cmath, jonka lisäksi NameSpace on vähintäänkin omassa otsaketiedostossaan.Dimple wrote:Mutta mitä hyötyä on tehdä näin?Tuossahan menetetään kaikki nimiavaruudesta saatava hyöty.Code: Select all
namespace NameSpace { void func() {} } using namespace NameSpace; int main() { func(); return 0; }
Code: Select all
namespace NameSpace = ns
ns::func()
- Dibalo
- Advanced Member
- Posts: 298
- Joined: Mon Aug 27, 2007 8:12 pm
- Location: Espoo, Finland
- Contact:
Re: C++ Projektit / Esimerkki koodit
Jos foorumisoftassa olisi tykkää-painike, niin käyttäisin.Dimple wrote:Mikä idea on laittaa kaikki funktiot nimiavaruuteen...
Re: C++ Projektit / Esimerkki koodit
ratingit toimivat paremmin
viimeksi kun näin plus-arvostelua kokeiltavan ei siitä tullut mitään
viimeksi kun näin plus-arvostelua kokeiltavan ei siitä tullut mitään
- Sami The Great
- Advanced Member
- Posts: 485
- Joined: Tue Aug 28, 2007 4:15 pm
- Contact:
Re: C++ Projektit / Esimerkki koodit
Palasin itse takaisin C++:n maailmaan ja totesin, että foorumilla on ollut aika hiljaista sen suhteen viime aikoina, jos vertaa esim vuosia taaksepäin. Joten päätimpä nostaa tämän aiheen taas esille, jos joku innostuisi taas koodailemaan jotakin
Aloitin Cocos2D-x:lla uutta projektia, ja kirjastoa tarkemmin tutkaillessani huomasin, että se ei sisällä omaa resurssi manageria, joten päätin tehdä sellaisen itse. Jos joku joskus kyseisellä kirjastolla koodailee peliään ja kiroaa miksi kuvien lataaminen etukäteen on niin vaikeaa / ei halua käyttää aikaa ja päästä helpommalla, niin voit tulla tänne ja kopioida ehkei nopeimman, mutta toimivan resurssi managerin. Manageri pystyy lataamaan tekstuureita PNG-kuvista, musiikkia sekä ääniä. Halutessaan tietenkin tämä on helppo muokata vastaamaan myös jonkin toisen kirjaston tarkoituksia. Muuttaa vain AssetResource structista tekstuurin tyyppiä halutun kirjaston vastaavaksi ja korvaa loadCocos2D-funktion omalla, joka lataa vaikka SDL-surfacen.
Käyttö:
Manageri toimii singletonina ja näin ollen sitä voidaan käyttää missä tahansa kohtaa koodia.
Ennen käyttöä manageri pitää alustaa init()-funktiolla.
Manageri toimii niin, että se lataa resursseja taustalla yhden per frame, joten muista kutsua update()-funktiota aina joka framella. Latauksen päättymisen tiedät, kun isLoading() palauttaa false.
Resursseja lisätään latausjonoon load-funktiolla. HUOM! resurssi EI OLE käytössä heti tämän komennon jälkeen, vaan se lisätään ladattavien resurssien listalle. Voit tarkistaa onko resurssi ladattu isLoaded-funktiolla.
load-funktio tarvitsee myös parametriksi ladattavan resurssin tyypin. (RES_TYPE_TEXTURE, RES_TYPE_SOUND tai RES_TYPE_MUSIC) Kun olet kerran määritellyt resurssin tyypin, niin manageri hoitaa loput itsestään.
Muista vapauttaa ladatut tiedostot remove-komennolla tai vastaavasti voit tyhjentää koko managerin clear-komennolla.
Tässä vielä pieni esimerkki käytöstä:
EDIT: Parantelin vielä vähän koodia. Lisäsin setResourceFolder nimisen funktion helpottamaan, ettei tarvitse aina kirjoittaa root-kansion nimeä jokaisen resurssin lataukseen. Lisäksi justFinished funktiolla saa tiedon, että kaikki on ladattu valmiiksi kyseisen framen aikana. Tätä voi käyttää, jos tarvitsee vielä alustaa joitakin muuttujia ennen pelin aloittamista.
Sitten vielä itse koodi:
standards.h
ResourceManager.h
ResourceManager.cpp
Aloitin Cocos2D-x:lla uutta projektia, ja kirjastoa tarkemmin tutkaillessani huomasin, että se ei sisällä omaa resurssi manageria, joten päätin tehdä sellaisen itse. Jos joku joskus kyseisellä kirjastolla koodailee peliään ja kiroaa miksi kuvien lataaminen etukäteen on niin vaikeaa / ei halua käyttää aikaa ja päästä helpommalla, niin voit tulla tänne ja kopioida ehkei nopeimman, mutta toimivan resurssi managerin. Manageri pystyy lataamaan tekstuureita PNG-kuvista, musiikkia sekä ääniä. Halutessaan tietenkin tämä on helppo muokata vastaamaan myös jonkin toisen kirjaston tarkoituksia. Muuttaa vain AssetResource structista tekstuurin tyyppiä halutun kirjaston vastaavaksi ja korvaa loadCocos2D-funktion omalla, joka lataa vaikka SDL-surfacen.
Käyttö:
Manageri toimii singletonina ja näin ollen sitä voidaan käyttää missä tahansa kohtaa koodia.
Code: Select all
minioid::ResourceManager::getSingletonPtr()->"TÄHÄN KUTSUTTAVA METODI"
Manageri toimii niin, että se lataa resursseja taustalla yhden per frame, joten muista kutsua update()-funktiota aina joka framella. Latauksen päättymisen tiedät, kun isLoading() palauttaa false.
Resursseja lisätään latausjonoon load-funktiolla. HUOM! resurssi EI OLE käytössä heti tämän komennon jälkeen, vaan se lisätään ladattavien resurssien listalle. Voit tarkistaa onko resurssi ladattu isLoaded-funktiolla.
load-funktio tarvitsee myös parametriksi ladattavan resurssin tyypin. (RES_TYPE_TEXTURE, RES_TYPE_SOUND tai RES_TYPE_MUSIC) Kun olet kerran määritellyt resurssin tyypin, niin manageri hoitaa loput itsestään.
Muista vapauttaa ladatut tiedostot remove-komennolla tai vastaavasti voit tyhjentää koko managerin clear-komennolla.
Tässä vielä pieni esimerkki käytöstä:
Code: Select all
minioid::ResourceManager* myResMgr = minioid::ResourceManager::getSingletonPtr();
myResMgr->init();
myResMgr->load("ukkeli.png", minioid::RES_TYPE_TEXTURE);
myResMgr->load("rajahdys.wav", minioid::RES_TYPE_SOUND);
myResMgr->load("musiikki.mp3", minioid::RES_TYPE_MUSIC);
while(1) //MAINLOOP
{
myResMgr.update();
if(myResMgr.isLoading())
{
//Näytetään latausikkuna ja päivitetään vaikka latauspalkkia
}
else
{
//Kaikki on ladattu ja pyöritetään peliä
}
}
Sitten vielä itse koodi:
standards.h
Code: Select all
#ifndef CHA_STANDARDS_H
#define CHA_STANDARDS_H
#include <vector>
#include <string>
#include <algorithm>
#endif
Code: Select all
#ifndef CAM_ASS_MGR_H
#define CAM_ASS_MGR_H
#include "standards.h"
#include "cocos2d.h"
#include "SimpleAudioEngine.h"
namespace minioid
{
enum
{
RES_TYPE_TEXTURE = 1,
RES_TYPE_SOUND,
RES_TYPE_MUSIC,
};
struct AssetResource
{
std::string path;
int type;
cocos2d::CCTexture2D* texture;
};
class ResourceManager
{
public:
ResourceManager();
~ResourceManager();
//Use singleton pointer to control the manager. ResourceManager::getSingletonPtr->...
static ResourceManager* getSingletonPtr();
//Init the manager.
void init();
//Updates loading queue. Call this once per frame!
void update();
//Add load request to queue.
//path - relative file path
//resourceType - resource type. (RES_TYPE_TEXTURE) see enum.
void load(std::string path, int resourceType);
//Returns true if file has been already loaded.
//path - relative file path
bool isLoaded(std::string path);
//Removes and unload resource.
void remove(std::string path);
//Clears and unload whole manager.
void clear();
//Returns true if loading isn't completed yet. When false, you know loading is finished.
bool isLoading();
//Returns loading progress as float between 0 and 1. Use this for your progress bar etc.
float getProgressPercent();
//Get loaded texture
//filename - filename of loaded texture
//Warning! Use this method only after current resource is loaded! (you can check isLoaded())
cocos2d::CCTexture2D* getTexture(std::string filename);
//Return true if loading has JUST finished
bool justFinished();
//Set root folder for resources
//Default is "data"
void setResourceFolder(std::string path);
private:
std::string resFolder;
bool justFin;
int totalAssets;
int loadedAssets;
bool isLoadingAssets;
static ResourceManager* singleton_assetMgr;
std::vector<AssetResource> loadingQueue;
std::vector<AssetResource> loadedFiles;
void cocos2DLoad(AssetResource res);
void cocos2DUnload(AssetResource res);
};
}
#endif
Code: Select all
#include "ResourceManager.h"
namespace minioid
{
ResourceManager::ResourceManager()
{
}
ResourceManager::~ResourceManager()
{
}
ResourceManager* ResourceManager::singleton_assetMgr;
ResourceManager* ResourceManager::getSingletonPtr()
{
if(!singleton_assetMgr)
{
singleton_assetMgr = new ResourceManager();
}
return singleton_assetMgr;
}
void ResourceManager::init()
{
clear();
loadingQueue.clear();
loadedFiles.clear();
isLoadingAssets = false;
loadedAssets = 0;
totalAssets = 0;
justFin = false;
resFolder = "data";
}
void ResourceManager::update()
{
justFin = false;
if(!loadingQueue.empty())
{
AssetResource pathToLoad = loadingQueue.back();
cocos2DLoad(pathToLoad);
loadingQueue.pop_back();
if(loadingQueue.empty()) justFin = true;
}
loadedAssets = (int)loadedFiles.size();
totalAssets = ((int)loadingQueue.size())+loadedAssets;
if(loadingQueue.empty()) isLoadingAssets = false;
if(!loadingQueue.empty()) isLoadingAssets = true;
}
void ResourceManager::load(std::string path, int resourceType)
{
isLoadingAssets = true;
AssetResource fileToLoad;
fileToLoad.path = path;
fileToLoad.type = resourceType;
loadingQueue.push_back(fileToLoad);
}
bool ResourceManager::isLoaded(std::string path)
{
std::vector<AssetResource>::iterator it;
for(it=loadedFiles.begin(); it < loadedFiles.end(); it++)
{
AssetResource tempRes = *it;
if(path == tempRes.path) return true;
}
return false;
}
void ResourceManager::remove(std::string path)
{
std::vector<AssetResource>::iterator it;
for(it=loadedFiles.begin(); it < loadedFiles.end(); it++)
{
AssetResource tempRes = *it;
if(path == tempRes.path)
{
cocos2DUnload(tempRes);
loadedFiles.erase(it);
}
}
}
void ResourceManager::clear()
{
std::vector<AssetResource>::iterator it;
for(it=loadedFiles.begin(); it < loadedFiles.end(); it++)
{
AssetResource tempRes = *it;
remove(tempRes.path);
}
loadingQueue.clear();
loadedFiles.clear();
}
bool ResourceManager::isLoading()
{
return isLoadingAssets;
}
float ResourceManager::getProgressPercent()
{
if(totalAssets == 0) return 0;
return ((float)loadedAssets)/((float)totalAssets);
}
void ResourceManager::cocos2DLoad(AssetResource res)
{
std::vector<AssetResource>::iterator it;
for(it=loadingQueue.begin(); it<loadingQueue.end(); it++)
{
AssetResource tempRes = *it;
if(tempRes.path == res.path)
{
std::string loadPath = ""+resFolder+"/"+tempRes.path;
if(res.type == RES_TYPE_TEXTURE)
{
cocos2d::CCTexture2D* tex = cocos2d::CCTextureCache::sharedTextureCache()->addImage(loadPath.c_str());
tempRes.texture = tex;
loadedFiles.push_back(tempRes);
break;
}
if(res.type == RES_TYPE_SOUND)
{
CocosDenshion::SimpleAudioEngine::sharedEngine()->preloadEffect(loadPath.c_str());
}
if(res.type == RES_TYPE_MUSIC)
{
CocosDenshion::SimpleAudioEngine::sharedEngine()->preloadBackgroundMusic(loadPath.c_str());
}
}
}
}
void ResourceManager::cocos2DUnload(AssetResource res)
{
if(res.type == RES_TYPE_TEXTURE)
{
cocos2d::CCTextureCache::sharedTextureCache()->removeTexture(res.texture);
}
if(res.type == RES_TYPE_SOUND)
{
CocosDenshion::SimpleAudioEngine::sharedEngine()->unloadEffect(res.path.c_str());
}
}
cocos2d::CCTexture2D* ResourceManager::getTexture(std::string filename)
{
std::vector<AssetResource>::iterator it;
for(it=loadedFiles.begin(); it<loadedFiles.end(); it++)
{
AssetResource tempRes = *it;
if(tempRes.path == filename) return tempRes.texture;
}
return 0;
}
bool ResourceManager::justFinished()
{
return justFin;
}
void ResourceManager::setResourceFolder(std::string path)
{
resFolder = path;
}
}
http://www.rockodilegames.com
CoolBasickin käyttäjä vuodesta 2004.
CoolBasickin käyttäjä vuodesta 2004.