Diablo inventory

BlitzMax Forums/BlitzMax Programming/Diablo inventory

verfum(Posted 2007) [#1]
Has anyone ever tried creating a Diablo style inventory? I'm going to tackle this soon, just wanted to know if anyone has already made a start, or finish?

As in you click on an object and drag it to the inventory and you can only drop it in if there is the space, i.e. every object uses a certain number of spaces.

Thanks.


Czar Flavius(Posted 2007) [#2]
What is your current skill level? Do you know how to drag and drop objects, or is it just this problem-specific you need help with?


verfum(Posted 2007) [#3]
Yeah that part of it isn't going to bother me, I've been programming a while, it's the detecting the boxes with the weapon box area, that kind of stuff, I'll tackle it during the week, I just wanted to see if anyone had already made a start on it.


CS_TBL(Posted 2007) [#4]
should be a cake o' peace..


Czar Flavius(Posted 2007) [#5]
Find out the starting and ending x and y coordinate of the box, and see if the mouse pointer is within that area.


verfum(Posted 2007) [#6]
cake o' peace LOL! probably will be.

It's more the object being dragged that needs to do the detecting, not the cursor.


CS_TBL(Posted 2007) [#7]
One of the most known design methods: seperate user interaction, visualization and implementation. What you need to have is just inventory *technically*, and some methods to compare another object and see how it fits. You should be comparing that by just using methods.. without gfx or mouse input. Later on, when it all works, you'll be sending mouse events to such methods, and you'll display your inventory.


verfum(Posted 2007) [#8]
yeah sounds like a good plan, just started working on it now.


Chroma(Posted 2007) [#9]
I'd use an array of a type. The type would be called something like TInvSlot (Inventory Slot). Make a field with the img, x, y, width, height, and type pointer TItem type. If the TItem pointer is null then it can recieve an item. If mouse is within the TInvSlot x,y,w,h and mousehit(1) then swap the item pointer from the TInveSlot type to the MousePointer containter type. Or you can just attach an TInvSlot to the mouse pointer by updating the TInvSlot's x,y to MouseX() and MouseY() so the Item Image moves along with the mouse pointer.

Type TInvSlot
   Field x:Int, y:Int, w:Int, h:Int
   Field item:TItem

   Method Draw()
      If self.item <> Null
         DrawImage item.image, self.x, self.y
      Endif
   End Method
End Type

Type TItem
   Field image:TImage

   Method Draw(x:Int, y:Int)
      DrawImage self.image, x, y
   End Method
End Type

Function MouseOver:Int(x%,y%,w%,h%)
   If MouseX() > x And MouseX() < x + w
      If MouseY() > y And MouseY() < y + h
         Return True
      Endif
   Endif
End Function
You would only draw the little item graphic image if it was in a slot. Either the inventory or the mouse slot. That way you don't need xy fields for the TItem.

Then in the loop see if the mouse is over a slot like this:
If MouseOver(slot.x, slot.y, slot.w, slot.h) = True

Then if the mouse slot is unoccupied transfer the item from the inventory slot to the mouse slot:
If MouseHit(1)
   If invSlot.item <> Null
      If mouseSlot.item = Null
         mouseSlot.item = invSlot.item
         invSlot.item = Null
      Endif
   Endif
Endif

I think the inventory is a major part of an rpg and should really be tightly coded and speedy. If it takes me a couple of clicks to get an item to transfer or if the inventory is laggy, I'll just stop playing the game. It's a major pet peeve of mine.

Hope this gives you some ideas!


ckob(Posted 2007) [#10]
let me see if I can dig up some of my old rpg code.


verfum(Posted 2007) [#11]
Ah great, your mouseover function worked fairly well, I've been stuck on it! Only problem is it's only picking the item up from the top left corner? I'm drawing the slots as you would tiles, so the slots for the inventory are drawn like this:
For Local x:Int = 0 Until m_slotColumns;
			For Local y:Int = 0 Until m_slotRows;
			
				If (m_selected) 
					If (x+m_slotX) >=0 And (x+m_slotX) <= (m_slotColumns) And (y+m_slotY) >=0 And (y+m_slotY) <= (m_slotRows) Then 
						DrawImage item_slot_image, (x*m_slotWidth)+MouseX(), (y*m_slotHeight)+MouseY();
					EndIf
				Else
					If (x+m_slotX) >=0 And (x+m_slotX) <= (m_slotColumns) And (y+m_slotY) >=0 And (y+m_slotY) <= (m_slotRows) Then 
						DrawImage item_slot_image, (x*m_slotWidth)+m_posX, (y*m_slotHeight)+m_posY;
					EndIf
				EndIf
				
			Next
		Next

and for the mouse over I'm doing it in a similar way, but it's only grabbing it in the very top left?
For Local x:Int = 0 Until m_slotColumns;
			For Local y:Int = 0 Until m_slotRows;
				
					If MouseOver(m_posX, m_posY, m_slotWidth, m_slotHeight) = True Then
					m_selected = True;

				EndIf
			Next
		Next



verfum(Posted 2007) [#12]
Okay done that, I forgot to * the m_slotWidth and Height by the Rows and Columns, I'm just having problem with the when you release the mouse button, need to lay it down now.


TaskMaster(Posted 2007) [#13]
Diablo had an inventory system where items had size, like a bow might take up 6 slots: a matrix 2 across, and 3 down.

So, what he would need to do is know the dimensions of the item, then find the inventory location he is trying to put the item in, by finding what slot the top left corner of the item is in, then check the inventory for that matrix of slots and see if they are all empty. Then, if they are, allow the item to be dropped and it will take up those slots.


Chroma(Posted 2007) [#14]
Here's a working sample for ya Verfum. Just use any 32x32 PNG image you have where it loads the .png

'Diablo Style Inventory System
'by Chroma
'Dec 17, 2007

Graphics 800,600

Local mainInventory:TInventory = New TInventory
mainInventory.SetParam(4,2,32)	'Set the inventory to be 4 across and 2 high and 32x32 in size
mainInventory.SetPos(300,200)

Local mouseSlot:TSlot = New TSlot
mouseSlot.item = New TItem
mouseSlot.item.image = LoadImage("sword001.png")	'Load any 32x32 PNG image here

Local mx:Int, my:Int
Local LMH:Int

MoveMouse 400,300

While KeyDown(KEY_ESCAPE)=False And AppTerminate()=False
Cls

	'Get Mouse Info
	mx = MouseX()
	my = MouseY()
	LMH = MouseHit(1)

	'Hide the cursor if player is moving an item
	If mouseSlot.item <> Null
		HideMouse 
	Else
		ShowMouse
	EndIf
	
	If LMH = True
		Local slot:TSlot
		For slot = EachIn mainInventory.SlotList
			If MouseOver(mainInventory.x+slot.x, mainInventory.y+slot.y, slot.w, slot.h) = True
				'Transfering from Mouse Slot to Inventory Slot
				If mouseSlot.item <> Null
					If slot.item = Null
						slot.item = mouseSlot.item
						mouseSlot.item = Null
					EndIf
				Else
				'Transferring from Inventory Slot to Mouse Slot
					If slot.item <> Null
						mouseSlot.item = slot.item
						slot.item = Null
					EndIf
				EndIf
			EndIf
		Next
	EndIf

	mainInventory.Render()
	mouseSlot.Render(mx,my)

Flip
Wend
End


Type TInventory
	Field x:Int, y:Int, size:Int
	Field SlotList:TList = New TList
	
	Method SetPos(x%,y%)
		self.x = x
		self.y = y
	End Method
	
	Method SetParam(x%,y%,s%)
		Local a%, b%
		For b = 0 To y-1
			For a = 0 To x-1
				Local slot:TSlot = New TSlot
				slot.x = a*s
				slot.y = b*s
				slot.w = s
				slot.h = s
				slot.border = True	'so you can see the slot boundary temporary
				self.SlotList.AddLast(slot)
			Next	
		Next
	
	End Method
	
	Method Logic()
	
	End Method
	
	Method Render()
		Local slot:TSlot
		For slot = EachIn self.SlotList
			slot.Render(self.x, self.y)
		Next
	End Method
	
End Type

Type TSlot
	Field x:Int, y:Int, w:Int, h:Int
	Field item:TItem
	Field border:Int
	
	Method Render(xorigin%, yorigin%)
		If self.border = True
			Local xp% = xorigin + self.x
			Local yp% = yorigin + self.y
			DrawLine xp, yp, xp+self.w, yp
			DrawLine xp+self.w, yp, xp+self.w, yp+self.h
			DrawLine xp+self.w, yp+self.h, xp, yp+self.h
			DrawLine xp, yp+self.h, xp, yp		
		EndIf
		If self.item <> Null
			DrawImage self.item.image, xorigin + self.x, yorigin + self.y
		EndIf
	End Method
End Type

Type TItem
	Field image:TImage
End Type


Function MouseOver:Int(x%, y%, w%, h%)
	If MouseX() > x And MouseX() < x + w
		If MouseY() > y And MouseY() < y + h
			Return True
		EndIf
	EndIf
End Function



verfum(Posted 2007) [#15]
Wow, that's excellent, you beat me too it :( I'll adapt that code into mine, thanks for your help!