Egy kérdésem lenne, ami nem teljesen Blitz Basic-es, hanem a Blitz3D-nek a FreeBasic-be történő beépítésével, vagyis az openb3d.bi modullal kapcsolatos.
Szóval, készítettem kis 3D-s programomban egy felületet, ami a különféle kiírásokat mutatja, vagyis HUD-ot. Ezt a HUD-ot kellene valahogy átméreteznem, pl. hogy olyan széles legyen, mint a képernyő szélessége.
Az imagecreate utasítással hozom létre hozzá a képet, a CreateTexture-rel meg egy textúrát hozzá. De az a probléma, hogy bármekkora méretértékeket adok meg ezeknek, mindig ugyanakkora kék négyzetet kapok a képernyőn. Teljesen tanácstalan vagyok, hogy ezt mi okozza és hogyan lehetne megoldani.
De itt a kód ezzel kapcsolatban:
#Include "openb3d.bi" #include "fbgfx.bi"
Using FB
const ksz=800 : const km=600
ScreenRes ksz,km,32,,&h10002 Graphics3d ksz,km
dim shared as any ptr hudkepe,hudszovegtex,kamera,kepahudhoz
kepahudhoz=imagecreate(128,32,32) '128*32-es, de mégsem akkora lesz!
Abban a kérdésben szeretném a segítségeteket kérni, hogy adott egy kúp, amit tudunk mindenfelé forgatni a billentyűzet gombjaival. Viszont hogy lehet ezt úgy mozgatni, hogy mindig a csúcsa felé mozduljon el, bármerre is van az elforgatva? Megoldható ez a MoveEntity paranccsal?
Sajnos ismét elakadtam a programozással, most a következő két kérdésem van: az egyik az, hogy hogyan lehet azt megcsinálni, hogy a 3D-s térben a tárgyak ne csak részben látszódjanak, azaz ne az legyen, hogy ködszerűen látszik egy része, a másik meg még nem, hanem egyre kisebbedve látszódjanak a távoli tárgyak? A másik pedig az, hogy hogyan lehet azt megcsinálni, hogy az ég és a talajtextúrák a távolban összeérjenek, és úgy is maradjanak attól függetlenül, hogy a játékos megy vagy forog a térben? Mert most az van, hogy vagy egy nagy gömböt csinálok égboltnak, azon az égtextúrával, de ez "félbevágja" a határán levő tárgyakat (lásd: 1. kérdés problémája) vagy a createplane() és a turnentity()-vel csinálok egy fordított síkságot, de ez is azt csinálja. Mi a legjobb megoldás erre?
Átnéztem a példaprogramokat, és vegyesen használják ezt vagy azt a módszert, de a saját programomba átültetve valahogy nem működnek. :-(
Ghoezeke, nem azzal van baj, hogy a Case elágazásban szereplő letrehozakadaly() és letrehozalak() függvényeken belül hívok egy másik címkét a restore-val? Vagyis ha egy függvényben így átugrok egy másik címkére, akkor az hatással lesz a programkódnak a szóbanforgó függvény utáni részére is?
Várjunk csak, van egy olyan gyanúm, hogy a 16 és 1 számok az X és Y térközből, amik az objektumok méretei, keverednek valahogy be a data-kiolvasásba... csak tudnám, hogyan.
Az imént megint foglalkoztam a programommal. A fő (és eddig nem működő) dolog az lenne benne, hogy a pálya elemeit rakja ki a .palya data-szerkezetben megadott elhelyezései szerint. A "0" jelenti, hogy nincs ott semmi, tehát csak arrébb kell lépni néhány képpontnyit jobbra. A "-" egy 16*16-os kockát jelent, egy akadályt, ami elhelyezése után 16 képpontot kell arrébbmenni jobbra, és az Y térköz is 16 lesz. Végül a "*" jelenti a játékosobjektumot, ami középen van, és csak egy kell belőle. Mindezen dolgokat a következő függvény végzi el (rosszul valamiért):
Function palyakirako() Restore palya Read szelesseg Read magassag xterkoz=1 : yterkoz=1 : xhely=0 : yhely=0 For j=1 To magassag For i=1 To szelesseg Read ertek$ Select ertek$ Case "0" Text xhely,yhely,ertek$ xhely=xhely+16 : yterkoz=16 Case "-" Text xhely,yhely,ertek$ letrehozakadaly(xhely,yhely) xhely=xhely+16 : yterkoz=16 Case "*" Text xhely,yhely,ertek$ letrehozalak(xhely,yhely) xhely=xhely+16 : yterkoz=16 Default Text xhely,yhely,">"+ertek$+"<" xhely=xhely+StringWidth(">"+ertek$+"<") : yterkoz=StringHeight(">"+ertek$+"<") End Select If xhely>=GraphicsWidth() Or i=szelesseg xhely=0 : yhely=yhely+yterkoz EndIf Next Next End Function
Már tettem be egy DEFAULT ágat is, hogy lássam, mi miatt nem rakja ki rendesen a dolgokat, vagyis a 16 darab akadálykocka helyett csak egyet, és játékosobjektumot egyet sem. Így a mellékelt képen látható eredményt kaptam, vagyis kirak egy kockát (a 16-ból), mellé a 16-os számot írja ki kétszer, és a data-szerkezet széleire 1-eseket (azért vannak > és < között, hogy jobban kiemeljem őket). Ez miért lehet és hogyan orvosolható?
Egyrészt a pálya talán változik, ezért a pályakirajzolót paraméterrel kellene megoldani, bemenő a pálya neve, pl. palya1, palya2, stb, és a data-read azokon mozdul.
Az akadályok viszont valszeg azonosak, ezeken nem minden alkalommal indítunk data-read típusú beolvasást, ez sokkal hosszabb, hanem csak egyszer, az indításnál, és globál tömbbe töltjük azokat, és a kirajzolást már ezekből a tömbökből direkt végezzük. A grafikus játék mindig hardverkritikus, ezért mindig szigorúan minimalizáljuk a műveleteket, semmi feleslegesnek nincs helye.
Továbbra sem látom azt, amit javasoltam korábban, van többszáz nullás data, és csak pár az aktív, - vagy *. Csak ezeket kell a datába tenni, a nulla legyen alapértelmezett. Itt is spórolhatsz többezer gépi ciklust. Nézd vissza, mit írtam.
A típusaid továbbra sem konzekvensek, és ismét feleslegességek vannak.
Az xhely-yhely egésszám, te meg stringet teszel bele, ráadásul nem is értem, ha egy ertek$ van beolvasva, mit csinál abból a StringWidth és párja?
A select a felső függvényben rossz, duplázás, önismétlés.
Így jó:
Kiveszed előre az azonosságokat:
Text xhely,yhely,ertek$ xhely=xhely+StringWidth(ertek$) : yterkoz=StringHeight(ertek$)
És a case csak az aktív műveleteknél kell, természetesen kikommentelve, ha élesbe mész:
Select ertek$ Case "-"
És a függvényhívás előtt adj paramétert, ne utána!!! xhely = Valami_numerikus_érték_amit_megért_hívott_függvény
yhely = dettó
;letrehozakadaly(xhely,yhely) Case "*"
itt is értékadás, más numerikus adat. ;letrehozalak(xhely,yhely) End Select
A mintának tett letrehozakadaly-ban visszatértél a felesleges változóhoz, a
rajzxhely=rajzxhely+1
nem kell, maga a for-next lép egyet, a változó csak időpocsékolás. Tessék kitalálni a jó algoritmust!
Ilyen meg nincs, önmagát önmagának nem kell értékadni:
alakkepe=alakkepe
Aztán a letrehozakadaly további súlyos problémája, hogy megint data-t olvas, mindig visszaállítja a read$-et az első elemre (restore). Nem lehet többször adatot olvasni, azt egy helyen kell, és világos logikai felépítésű függvényekkel.
Szóval nem csodálom, hogy nem megy, lépésről lépésre írd át, ez így sosem lesz kész.
Mégis inkább csak félsiker van. Ugyanis azt már kiírja rendesen a data-szerkezetből, hogy milyen írásjelekből áll, a következő függvénnyel:
Function palyakirako() Restore palya Read szelesseg Read magassag xterkoz=1 : yterkoz=1 : xhely=0 : yhely=0 For j=1 To magassag For i=1 To szelesseg Read ertek$ Select ertek$ Case "0" Text xhely,yhely,ertek$ xhely=xhely+StringWidth(ertek$) : yterkoz=StringHeight(ertek$) Case "-" Text xhely,yhely,ertek$ ;letrehozakadaly(xhely,yhely) xhely=xhely+StringWidth(ertek$) : yterkoz=StringHeight(ertek$) Case "*" Text xhely,yhely,ertek$ ;letrehozalak(xhely,yhely) xhely=xhely+StringWidth(ertek$) : yterkoz=StringHeight(ertek$) End Select If xhely>=GraphicsWidth() Or i=szelesseg xhely=0 : yhely=yhely+yterkoz EndIf Next Next End Function
a Data-szerkezet pedig így néz ki:
.palya Data 16 Data 16 Data "0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0" Data "0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0" Data "0","0","-","-","0","0","0","0","0","0","0","0","0","0","0","0" Data "0","0","-","-","0","0","0","0","0","0","0","0","0","0","0","0" Data "0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0" Data "0","0","0","0","0","0","0","0","0","0","0","-","-","0","0","0" Data "0","0","0","0","0","0","0","0","0","0","0","0","-","0","0","0" Data "0","0","0","0","-","0","0","0","0","0","0","0","-","0","0","0" Data "0","0","0","0","0","0","0","*","0","0","0","0","-","0","0","0" Data "0","0","0","0","0","0","0","0","0","0","0","-","-","0","0","0" Data "0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0" Data "0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0" Data "0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0" Data "0","0","-","-","-","-","0","0","0","0","0","0","0","0","0","0" Data "0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0" Data "0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"
Tehát a fő programciklusba téve a függvényt, helyesen kiírja az értékeket, de viszont az objektumokat nem hozza létre megfelelően az xhely,yhelyen, ha kiveszem őket a megjegyzésből. Konkrétan 1 db-ot hoz létre és azt sem a megfelelő helyen.
Így néz ki az objektumlétrehozás az akadály esetében, amit a "-"jel testesít meg a pályán:
Function letrehozakadaly(xhely,yhely) alak.akadaly=New akadaly alakx=xhely alaky=yhely alakid=id_adas("akadalyoknak") Restore akadalykep Read szelesseg Read magassag alakszelessege=szelesseg alakmagassaga=magassag alakkepe=CreateImage(szelesseg,magassag) SetBuffer ImageBuffer(alakkepe) rajzxhely=x rajzyhely=y For j=1 To magassag For i=1 To szelesseg Read akertek If akertek<>0 Then kiszinezo(akertek,rajzxhely,rajzyhely) rajzxhely=rajzxhely+1 If i=szelesseg rajzyhely=rajzyhely+1 rajzxhely=rajzxhely-szelesseg EndIf Next Next alakkepe=alakkepe SetBuffer BackBuffer() End Function
És fogalmam sincs, mi lehet a baj... valaki tud segíteni?
Read ertek$ Select Str(ertek) Case "0" Text xhely,yhely,Str(ertek) Case "-" Text xhely,yhely,Str(ertek) Case "*" Text xhely,yhely,Str(ertek) End Select
és így most már végre a megfelelő írásjeleket írta ki a szövegesként megadott Data-szerkezetből. Nagy kő esett le a szívemről, de még mindig nem értem egészen...
Ha stringbe írsz (valami1palyasor$), akkor abba stringbe konvertált numerikust írj. Az i*szelar stb. numerikus érték, ilyen okozhat hibát, mert megint egy automatikus konverzióra kényszeríted a compilert.
A basicokban a numerikust általában a str$ függvénnyel teszik át.
Valami még mindig nem jó. Csináltam egy kisebb "pályát", azaz data-szerkezetet a jobb átláthatóság végett, ami ennyi:
.palya
data 3
data 3
data 0,0,0
data 0,1,0
data 0,0,0
és ebből a következő függvény olvassa ki az értékeket:
Function palyakirako() Restore palya Read szelesseg Read magassag szelar=GraphicsWidth()/szelesseg magar=GraphicsHeight()/magassag For j=0 To magassag-1 For i=0 To szelesseg-1 Read ertek For valami1.egermutato=Each egermutato valami1palyasor$=valami1palyasor$+","+i*szelar+"/"+j*magar+"Értéke: "+ertek Next Select ertek Case 1 letrehozalak(i*szelar,j*magar) Case 0 letrehozakadaly(i*szelar,j*magar) End Select Next Next End Function
Itt az egérmutató objektumot használom arra is, hogy kiírasson bizonyos dolgokat, a hibakeresés okából. És ez mutatja érdekes módon Értéke-nek, hogy:
0,16,16,1,16,16,0,16,16
tehát mintha valami átírná a pálya datákat a következőre:
0,16,16
1,16,16
0,16,16
pedig csak 0 meg 1 szerepel benne.
Gőzöm sincs, hogy ez miért lehet. Valaki tudna segíteni benne?
Köszi, ezeket is átnézem. Eddig csupán annyiból állt a hibakeresés nálam, hogy futtatás előtt "F7", meg ha valami hiba volt, akkor amit csak lehetett, változók, értékek, stb. a text-tel kiírattam, hogy mégis valahogy nagyjából képben legyek a futtatás közbeni dolgokkal kapcsolatban.
De ilyen alaposan még nem tudtam elmerülni a BB tulajdonságaival, jellegzetességeivel, amit leírtál, hiszen csupán a súgója áll rendelkezésemre, mint áttanulmányozható dokumentum, úgyhogy nekem ezek újdonságok, amit írsz, úgyhogy mégegyszer köszönet érte.
Nem ismerem a BB típuskonvertálási automatizmusát, lehet, onnan jön a hiba.
A random módszered, ami jó, egésszámot ad, a read szöveget. A basic az érték nélküli szöveget automatikusan nullára konvertálja, így a "-" és a "*" is az lesz, tehát nem látsz értéket a két tömbödben.
Vagy számot olvass be, vagy a szöveget a case-eknél konvertáld.
És ezzel kapcsolatban tud valaki segíteni? Az a gond, hogy ebből a DATA-szerkezetből kellene kiolvasni a játékban a létrehozandó objektumok koordinátáit. A "*" jelenti a játékos objektumának a helyét, a "-" pedig egy akadálykockát. De valamiért a képen látható ciklusos "READ$" kiolvasás nem hozza létre. Mi lehet a baj?
Minden módszer végigvizsgálja az elemeket, nincs más. Logikailag lehet gyorsítani, soklépcsős beágyazásokkal, ahol a lehető leggyorsabban eldöntendő, hogy érdemes-e továbbvizsgálni az adott objektumot.
Na meg persze egészszám használattal, 4 bájtos illesztéssel, szöveg- és lebegőpontos változók kerülésével. És kiszórni minden felesleges műveletet.
Igen, lehet hogy az általad ajánlott módszert fogom végülis alkalmazni. Csak tudod, furcsa egy kicsit egy objektumorientált nyelv után (a Game Maker GML-je) belekóstolni az ilyen soros vagy minekmondják programnyelvbe. Igazság szerint én a GM módszereit próbáltam beleerőltetni a Blitzbe. De amúgy nem terhelő ez a "mindig végigfutni az objektumokon" elv? Igaz, az "exit"-tel ki lehet lépni, ha megvan a keresett dolog...
Nem kell szívbajosnak lenni, jó méretes tömböt lefoglalsz induláshoz, aztán ha betelik, redim preserve átdefiniál. De jobb egyszerre, gyorsabb a játék, nem kell állandóan tömbhatárt ellenőrizni. Ránézésre sem éred el a memória ezredrészét, akkor mit szenvedjünk?
De továbbra sem látom a problémád, vannak az objektumnak koordinátái, végig kell menni a létező aktív elemeken, és amelyikbe beleesik az ütköző elem, ott az id.
Az objektumok ütközésekor szeretném lekérdezni az akadályobjektum id-jét, hogy aztán más műveleteket is el tudjak végezni vele (pl. írni egy akadálykikerülő algoritmust).
Talán a tömbök is jók lennének, de annál már a kezdet kezdetén meg kell adni, hogy hány elemű lesz.
A típus nem használható programokban programozható műveletekre, azok csak leírók egy felhasználói adatrekord felépítéséhez, illetve több/sok azonos rekordnál tömbről beszélünk.
Tehát nem.
Viszont maguk a rekordok igen, azok tartalmazhatnak más tömbökre mutató adatokat, tipikusan ilyen az indextömb.
Jobb lenne, ha ilyen homályos kérdések helyett leírhatnád, mit is akarsz. Az id-k kezelése nem mond semmit.
Azt szeretném megtudni, hogy hogyan lehet azt megcsinálni, hogy legyen egy fő típusgyűjtemény és azon keresztül elérhetők legyenek más típusok?
Konkrétan arról van szó, hogy azonosítószámokat (id) adnék a játékomban az egyes objektumoknak, de mivel több típus van (pl. type jatekos, type akadaly), ezeket külön-külön kellene végigpörgetni egy-egy FOR-EACH ciklussal. Ezt kellene valahogy egybefogni, hogy mondjuk legyen egy fő típus (pl. type minden_ids_dolog), és azon lefuttatva a ciklust adni minden olyan objektumnak id-t, amelynek csak kell.
Mert eddig úgy csináltam, hogy csak egy típus (type minden_dolog) volt a játékban, és ezen át egyszerű volt id-t adni, de most úgy készítenék egyjátékot, hogy többféle típus lesz benne.
Köszönöm a válaszaidat; át is tértem a beépített DrawImage-re, és most már megfelelő sebességgel fut a programom.
Amúgy mennyire lehet elterjedt a BB3D használata itt Magyarországon? Mert nem nagyon találok ezzel kapcsolatos magyar oldalakat (lehet, hogy az enyém úttörő jellegű etéren?), meg ez a fórum se pörög túlságosan.