Yksinkertaisen inventoryn hallinta

Oletko tehnyt jotain, mistä muut voisivat hyötyä. Postita vinkit tänne.
Post Reply
User avatar
axu
Devoted Member
Posts: 854
Joined: Tue Sep 18, 2007 6:50 pm

Yksinkertaisen inventoryn hallinta

Post by axu »

Tässä yksinkertaiset funktiot inventoryn hallintaan:

Code: Select all

SAFEEXIT OFF
AddItem("Gold", 1000)

Repeat
	Scroll = Max(0, Scroll - MouseMoveZ())
	
	If KeyHit(cbKey1) Then
		AddItem("Gold", -300, True, True)
		AddItem("Potion")
	EndIf
	If KeyHit(cbKey2) Then
		AddItem("Potion", -1)
	EndIf
	If KeyHit(cbKey3) Then
		AddItem("Gold", Rand(-500, -200), True, True)
		AddItem("Letter " + Chr(Rand(65, 90)))
	EndIf
	
	If KeyHit(cbKeyS) Then SaveInventory()
	If KeyHit(cbKeyL) Then LoadInventory()
	
	Text 1, 1, "Press 1 to buy potion for 300G, 2 to drink potion."
	Text 1, 15, "Press 3 to buy random letter at random price."
	If ItemCount("Gold") <= 0 Then
		Text 1, 30, "You have no money, but shopkeeper gives you credit."
	EndIf
	
	DrawInventory(10, 50, 200, Scroll)
	Box 9, 49, 380, 200, 0
	
	Text 1, 280, "Press S to save inventory, L to load." 
	DrawScreen
Until EscapeKey()
//Poistetaan tallennustiedosto, tämä on vain esimerkkiä varten ettei jää ylimääräisiä tiedostoja lojumaan, tietenkään varsinaisessa pelissä moista ei tehdä
If FileExists("Inventory.dat") Then DeleteFile "Inventory.dat"
End


//Tästä alkaa varsinainen inventoryn hallintaosuus:
Type InventoryItem
	Field Name$
	Field Count
EndType


//Lisää tai vähentää tavaraa inventorysta. Jos Count on negatiivinen, tavaraa vähennetään. Oletuksena lisää yhden tavaran.
//AllowZero määrää, voiko inventory sisältää tavaraa nolla kappaletta. Jos AllowZero on asetettu epätodeksi, tavara tuhotaan inventorysta sen loppuessa
//AllowNegative määrää, voiko tavaraa olla vähempää kuin nolla. Jos AllowNegative on asetettu epätodeksi (False), funktio palauttaa -1 jos tavara loppui kesken
Function AddItem(ItemName$, Count = 1, AllowZero = 0, AllowNegative = 0)
	//Käydään tavarat läpi ja tutkitaan, löytyykö tavaraa valmiiksi inventorysta
	For iI.InventoryItem = Each InventoryItem
		If iI\Name = ItemName Then
			//Merkataan tavara löytyneeksi
			ItemExists = True
			
			//Lisätään tavaran määrää
			iI\Count = iI\Count + Count
			
			//Jos saldo menee miinukselle ja sitä ei ole sallittu, asetetaan määrä nollaksi ja palautusarvo -1:ksi
			If iI\Count < 0 And AllowNegative = False Then
				iI\Count = 0
				//Asetetaan palautusarvoksi -1
				RetVal = -1
			EndIf
			
			If iI\Count = 0 And AllowZero = False Then
				//Jos tavara loppuu, tuhotaan se inventorysta
				Delete iI
			EndIf
			
			//Ei jatketa etsintää
			Exit
		EndIf
	Next iI
	
	//Jos tavaraa ei löytynyt inventorysta, luodaan se
	If ItemExists = False Then
		//Jos olematonta tavaraa yritetään vähentää ja sitä ei ole olemassa, ei vähennetä
		If Count < 0 And AllowNegative = False Then
			Count = 0
			//Asetetaan palautusarvoksi -1
			RetVal = -1
		EndIf
		
		//Tavaraa ei luoda, jos sitä on nolla kpl ja sitä ei ole sallittu
		If Not (Count = 0 And AllowZero = False) Then
			nI.InventoryItem = New(InventoryItem)
			nI\Name = ItemName
			nI\Count = Count
		EndIf
	EndIf
	
	Return RetVal
EndFunction

//Palauttaa haetun tavaran määrän
Function ItemCount(ItemName$)
	//Etsitään inventorysta tavaraa nimeltä ja palautetaan sen määrä
	For iI.InventoryItem = Each InventoryItem
		If iI\Name = ItemName Then Return iI\Count
	Next iI
	//Jos tavaraa ei löytynyt, palautetaan nolla
	Return 0
EndFunction

//Tulostaa inventoryn sisällön annettuihin koordinaatteihin. Oletuksena inventory piirretään koko ikkunalle.
//Scroll määrää ensimmäisen tavaran järjestysnumeron. Oletuksena lista näytetään ensimmäisestä tavarasta lähtien.
//RowHeight määrää rivinkorkeuden.
Function DrawInventory(X = 0, Y = 0, Height = 0, Scroll = 0, RowHeight = 0)
	//Jos korkeutta ei ole määritetty, tulostetaan ruudun alalaitaan saakka
	If Height = 0 Then Height = ScreenHeight() - Y

	//Jos rivinkorkeutta ei olla kerrottu, asetetaan se tekstin korkeudeksi
	If RowHeight = 0 Then RowHeight = TextHeight("A")
	
	//Tulostetaan listaa vain niin paljon kuin mahtuu ruudulle
	ItemsToShow = RoundDown(Float(Height) / RowHeight)
	
	ItemNo = 1
	For iI.InventoryItem = Each InventoryItem
		If ItemNo > Scroll Then
			Text X, Y + (ItemNo - Scroll - 1) * RowHeight, iI\Count + "x " + iI\Name
		EndIf
		
		ItemNo = ItemNo + 1
		If ItemNo > Scroll + ItemsToShow Then Exit
	Next iI
EndFunction

//Tallentaa inventoryn, oletuksena "Inventory.dat"-nimiseen tiedostoon.
Function SaveInventory(FileName$ = "Inventory.dat")
	//Tallennetaan inventoryn sisältö tiedostoon
	f = OpenToWrite(FileName)
		//Käydään läpi jokainen tavara ja kirjoitetaan se tiedostoon
		For iI.InventoryItem = Each InventoryItem
			WriteString f, iI\Name
			WriteInt f, iI\Count
		Next iI
	CloseFile f
EndFunction

//Lataa inventoryn, oletuksena "Inventory.dat"-tiedostosta.
Function LoadInventory(FileName$ = "Inventory.dat")
	//Tyhjennetään ensin inventory, ettei tavaroita voida kloonata lataamalla peli
	For iI.InventoryItem = Each InventoryItem
		Delete iI
	Next iI
	
	If FileExists(FileName) Then
		//Luetaan inventoryn sisältö tiedostosta
		f = OpenToRead(FileName)
			While Not EOF(f)
				nI.InventoryItem = New(InventoryItem)
				nI\Name = ReadString(f)
				nI\Count = ReadInt(f)
			Wend
		CloseFile f
	EndIf
EndFunction
Tämä on lähinnä rungoksi, tästä puuttuu mm. tavaroiden valitseminen ja järjestäminen. Inventoryn tulostusfunktio todennäköisesti kannattaa kuitenkin tehdä joka pelille erikseen, että tulee oikeannäköinen.

Alla lista funktioista ja niiden käytöstä:
  • AddItem(ItemName [, Count, AllowZero, AllowNegative])
    Lisää tai vähentää tavaraa inventorysta. Jos Count on negatiivinen, tavaraa vähennetään. Oletuksena lisää yhden tavaran.
    AllowZero määrää, voiko inventory sisältää tavaraa nolla kappaletta. Jos AllowZero on asetettu epätodeksi, tavara tuhotaan inventorysta sen loppuessa
    AllowNegative määrää, voiko tavaraa olla vähempää kuin nolla. Jos AllowNegative on asetettu epätodeksi (False), funktio palauttaa -1 jos tavara loppui kesken
  • ItemCount(ItemName)
    Palauttaa haetun tavaran määrän
  • DrawInventory([X, Y, Height, Scroll, RowHeight])
    Tulostaa inventoryn sisällön annettuihin koordinaatteihin. Oletuksena inventory piirretään koko ikkunalle.
    Scroll määrää ensimmäisen tavaran järjestysnumeron. Oletuksena lista näytetään ensimmäisestä tavarasta lähtien.
    RowHeight määrää rivinkorkeuden.
  • SaveInventory([FileName])
    Tallentaa inventoryn, oletuksena "Inventory.dat"-nimiseen tiedostoon.
  • LoadInventory([FileName])
    Lataa inventoryn, oletuksena "Inventory.dat"-tiedostosta.
Jostain syystä cbe:llä inventoryn lataus kaataa ohjelman. Vika näyttäisi olevan ReadString-funktiossa.
Jos tämä viesti on kirjoitettu alle 5 min. sitten, päivitä sivu. Se on saattanut jo muuttua :roll:
Image
User avatar
Combatti
Active Member
Posts: 101
Joined: Fri Jun 29, 2012 6:23 pm
Location: Kuhmo

Re: Yksinkertaisen inventoryn hallinta

Post by Combatti »

Ihan kiva systeemi. :D Tekstipohjaisiin peleihin ihan tyylikäs. Sinänsä melko hyödytön, sillä kuitenkin moni tekee oman invertory systeemin, muuttujilla. Mutta mikä sitten, hieno systeemi, joten stfu.
~Yhteiskuntaan kyllästynyt koodari.
skorpioni-cb
Advanced Member
Posts: 364
Joined: Wed Dec 03, 2008 3:48 pm
Location: Turku

Re: Yksinkertaisen inventoryn hallinta

Post by skorpioni-cb »

Combatti wrote:Ihan kiva systeemi. :D Tekstipohjaisiin peleihin ihan tyylikäs. Sinänsä melko hyödytön, sillä kuitenkin moni tekee oman invertory systeemin, muuttujilla. Mutta mikä sitten, hieno systeemi, joten stfu.
Kyllä muistipaloilla kannattaa tehdä, sillä se toimii samalla tavalla kuin tyypit, jotka on toinen tapa tehdä inventaario
En tiedä, mitä tiedän, mutta tiedän ettei se ole mitään kaunista.

I know not what I know, but I do know that it's not beautiful.
User avatar
Combatti
Active Member
Posts: 101
Joined: Fri Jun 29, 2012 6:23 pm
Location: Kuhmo

Re: Yksinkertaisen inventoryn hallinta

Post by Combatti »

skorpioni-cb wrote:
Combatti wrote:Ihan kiva systeemi. :D Tekstipohjaisiin peleihin ihan tyylikäs. Sinänsä melko hyödytön, sillä kuitenkin moni tekee oman invertory systeemin, muuttujilla. Mutta mikä sitten, hieno systeemi, joten stfu.
Kyllä muistipaloilla kannattaa tehdä, sillä se toimii samalla tavalla kuin tyypit, jotka on toinen tapa tehdä inventaario
Muistipalat ovat riskialttiimpia aloittelijoiden käsissä. Voi nimittäin aiheuttaa traumoja, jos kirjoittaa yli muistipalan koon ja sitten hups, kaatuu koko järjestelmä. :P Ja muuttujat ovat yksinkertaisempia, jos yksinkertaisuutta siis haetaan.
~Yhteiskuntaan kyllästynyt koodari.
User avatar
axu
Devoted Member
Posts: 854
Joined: Tue Sep 18, 2007 6:50 pm

Re: Yksinkertaisen inventoryn hallinta

Post by axu »

Combatti wrote:Muistipalat ovat riskialttiimpia aloittelijoiden käsissä. Voi nimittäin aiheuttaa traumoja, jos kirjoittaa yli muistipalan koon ja sitten hups, kaatuu koko järjestelmä. :P Ja muuttujat ovat yksinkertaisempia, jos yksinkertaisuutta siis haetaan.
Tällainen systeemi ei kyllä yksinkertaisemmaksi muutu tavallisia muuttujia käyttämällä. Tyyppejä käytin juuri yksinkertaisuuden vuoksi (tekee koodista helppolukuisempaa), mutta muistipalat on se paras tapa. Muistipalojen etuja tyyppikokoelmaan nähden on mm. helpompi pitää useita inventoryja, helpompi järjestellä, tallentaa ja ladata.

PS. lainatessa toisten tekstejä on hyvä tapa jättää sieltä aikaisempi keskustelu pois (ellei se aiheuta sekaannusta puuttuvan tekstiyhteyden vuoksi).
Jos tämä viesti on kirjoitettu alle 5 min. sitten, päivitä sivu. Se on saattanut jo muuttua :roll:
Image
User avatar
MetalRain
Active Member
Posts: 188
Joined: Sun Mar 21, 2010 11:17 am
Location: Espoo

Re: Yksinkertaisen inventoryn hallinta

Post by MetalRain »

Tulipa tästä mieleen että jos vähän graafisempaa tavaranhallintaa haluaa niin joskus ammoisina aikoina tein siihen suht näppärän pohjan. Värjätyt boxit on suht helppo muuttaa kunkin tavaran omaksi kuvaksi.

Code: Select all

SCREEN  800,600

Global RuudukkoLeveys, RuudukkoKorkeus

RuudukkoLeveys = 6
RuudukkoKorkeus = 8

Type poimittutavara
    Field nimi$
    Field ruudukkox
    Field ruudukkoy
    Field leveys_ruutuina
    Field korkeus_ruutuina
    Field siirretään
End Type


LisääTavaraluetteloon("keihäs",1,4)
LisääTavaraluetteloon("puteli",1,1)
LisääTavaraluetteloon("panssari",2,2)
LisääTavaraluetteloon("iso kivi",2,2)
LisääTavaraluetteloon("kengät",3,2)

Repeat
   
    Tavaraluettelo(20,20)
   
    DrawScreen
Forever



Function LisääTavaraluetteloon(nimi$,leveys_ruutuina,korkeus_ruutuina)

    For x=0 To RuudukkoLeveys-1
        For y=0 To RuudukkoKorkeus-1
       
            EpicFail = 0
            For p.poimittutavara = Each poimittutavara
                If BoxOverlap(x,y,leveys_ruutuina,korkeus_ruutuina,p\ruudukkox,p\ruudukkoy,p\leveys_ruutuina,p\korkeus_ruutuina) Or x+leveys_ruutuina>RuudukkoLeveys Or y+korkeus_ruutuina>Ruudukkokorkeus Then EpicFail = 1 :Exit
            Next p
            If Not EpicFail Then
                p.poimittutavara = New(poimittutavara)
                p\nimi = nimi$
                p\ruudukkox = x
                p\ruudukkoy = y
                p\leveys_ruutuina = leveys_ruutuina
                p\korkeus_ruutuina = korkeus_ruutuina
                Return ConvertToInteger(p)
            EndIf
       
        Next y
    Next x

End Function

Function Tavaraluettelo(x,y,ruutukoko=32)
    valittunimi$=""
   
    Box x,y,RuudukkoLeveys*ruutukoko, RuudukkoKorkeus*ruutukoko,0
   
    For p.poimittutavara = Each poimittutavara
        xx = x+p\ruudukkox*ruutukoko
        yy = y+p\ruudukkoy*ruutukoko
        w  = p\leveys_ruutuina*ruutukoko
        h  = p\korkeus_ruutuina*ruutukoko
       
        If p\siirretään=0 Then
            If BoxOverlap(MouseX(),MouseY(),1,1,xx,yy,w,h) Then
                valittunimi$ = p\nimi+" ("+p\ruudukkox+","+p\ruudukkoy+")"
                If MouseDown(1) And p\siirretään=0 Then
                    EpicFAIL = 0
                    For pp.poimittutavara = Each poimittutavara
                        If pp\siirretään=1 Then EpicFAIL = 1 : Exit
                    Next pp
                    If Not EpicFAIL Then p\siirretään=1 : pointer = ConvertToInteger(p)
                EndIf
            EndIf

            Color 0,255,0
            Box xx,yy,w,h,1
            Color 255,255,255
            Box xx,yy,w,h,0
        EndIf
       
    Next p
   
    For p.poimittutavara = Each poimittutavara
        If p\siirretään=1 Then
       
            w  = p\leveys_ruutuina*ruutukoko
            h  = p\korkeus_ruutuina*ruutukoko
   
            mx = min(Max(0,(MouseX()-x)/ruutukoko),RuudukkoLeveys-p\leveys_ruutuina)
            my = Min(Max(0,(MouseY()-y)/ruutukoko),RuudukkoKorkeus-p\korkeus_ruutuina)
               
            If MouseUp(1) Then
               
                For pp.poimittutavara = Each poimittutavara
                    If pp<>p Then
                        If BoxOverlap(mx,my,p\leveys_ruutuina,p\korkeus_ruutuina,pp\ruudukkox,pp\ruudukkoy,pp\leveys_ruutuina,pp\korkeus_ruutuina) Or mx+p\leveys_ruutuina>RuudukkoLeveys Or my+p\korkeus_ruutuina>Ruudukkokorkeus Then p\siirretään=0 : Return 0
                    EndIf
                Next pp
               
                p\ruudukkox = mx
                p\ruudukkoy = my
                p\siirretään=0
               
            ElseIf MouseDown(1) Then
            
                EpicFail=0
               ' If MouseMoveX() Or MouseMoveY() Then
                    For pp.poimittutavara = Each poimittutavara
                        If pp<>p Then
                            If BoxOverlap(mx,my,p\leveys_ruutuina,p\korkeus_ruutuina,pp\ruudukkox,pp\ruudukkoy,pp\leveys_ruutuina,pp\korkeus_ruutuina) Then EpicFail=1 :Exit
                        EndIf
                    Next pp
               ' EndIf
               
                If epicfail Then Color 255,0,0 Else Color 0,0,255
               
                Box x+mx*ruutukoko,y+my*ruutukoko,w,h,1
                Color 255,255,255
                Box x+mx*ruutukoko,y+my*ruutukoko,w,h,0
               
            EndIf
       
        EndIf
   
    Next p
   
   
    If valittunimi$<>"" Then
        tw = TextWidth(valittunimi$)
        th = TextHeight(valittunimi$)
        Color 0,0,0
        Box MouseX(),MouseY()-th-5,tw+5,th+5,1
        Color 255,255,255
        Box MouseX(),MouseY()-th-5,tw+5,th+5,0
        Text MouseX()+2,MouseY()-2-th,valittunimi$
    EndIf
   
End Function
Post Reply