Diablo Inventory, so far, with bug :(

BlitzMax Forums/BlitzMax Programming/Diablo Inventory, so far, with bug :(

verfum(Posted 2008) [#1]
Hi all, for a matter or weeks now I've been trying to create a diablo inventory system, which handles multi-sized objects, I've tried many different ways but all have failed so far, this is the method where I have got the furthest, okay, every slot created handles it's own collision detection, the inventory creates it's own slots and I have a mouse class which has it's own slots, it's very basic at the moment, just to demostrate to you the problem, if a collision is detected each slot draws a "C" that works, but if I change the color of the slot, it's changes the slot behind it?? Really odd :S See if any of you talented guys can spot the problem :D
SuperStrict

Type CSlot
	Field m_ID:Int;
	Field m_x:Int, m_y:Int;
	Field m_red:Int, m_green:Int, m_blue:Int;
	Field m_mouseSelected:Int = False;
	Field m_hover:Int = False;
	
	Function Create:CSlot(x:Int, y:int, red:Int, green:Int, blue:Int)
		Local slot:CSlot = New CSlot;
		slot.m_x = x;
		slot.m_y = y;
		slot.m_red = red;
		slot.m_green = green;
		slot.m_blue = blue;
		slot_list.AddLast(slot) ;
		return slot;
	End Function
	
	Method changeColor(red:Int, green:Int, blue:Int) 
		Self.m_red = red;
		Self.m_green = green;
		Self.m_blue = blue;
	End Method

	Method Draw(x:Int, y:Int) 
	
		Self.m_x = x;
		Self.m_y = y;
						
		DrawText(Self.m_x, Self.m_x, Self.m_y + 30) ;
		DrawText(Self.m_y, Self.m_x + 30, Self.m_y + 30) ;
		
		SetColor(m_red, m_green, m_blue) ;
		DrawRect(Self.m_x, Self.m_y, 30, 30) ;
		
		If Self.collide() 
			Self.changeColor(255, 255, 255) ;
			SetColor(255, 0, 0) ;
			DrawText("C", m_x + 10, m_y + 10) ;
		Else
			Self.changeColor(150, 150, 150) ;
		EndIf
			
	End Method
	
	Method collide:int()
    	
		For Local slot:CSlot = EachIn slot_list
			If slot <> Self Then
				If RectsOverlap(Self.m_x, Self.m_y, 30, 30, slot.m_x, slot.m_y, 30, 30) 
					return True;
				End If
			End If
		Next
		
	End Method
	
	Method RectsOverlap:int(x0:Int, y0:Int, w0:Int, h0:Int, x2:Int, y2:Int, w2:Int, h2:Int)
		If x0 > (x2 + w2) Or (x0 + w0) < x2 Then Return False
		If y0 > (y2 + h2) Or (y0 + h0) < y2 Then Return False
		Return True
	End Method
	
End Type

Type CInventory
	Field m_x:Int, m_y:Int;
	Field m_slot:CSlot;
	Field m_columns:Int, m_rows:Int;
	
	Function Create:CInventory(x:Int, y:int, columns:Int, rows:Int)
		Local inv:CInventory = New CInventory;
		inv.m_x = x;
		inv.m_y = y;
		inv.m_columns = columns;
		inv.m_rows = rows;
		inv.createSlots();
		entity_list.AddLast(inv) ;
		return inv;
	End Function
	
	Method createSlots() 
		For Local columns:Int = 0 Until m_columns
			For Local rows:Int = 0 Until m_rows
				m_slot = CSlot.Create(columns * 31 + m_x, rows * 31 + m_y, 150, 150, 150) ;
			Next
		Next
	End Method
	
	Method Draw() 

		For Local columns:Int = 0 Until m_columns
			For Local rows:Int = 0 Until m_rows
				m_slot.Draw(columns * 31 + m_x, rows * 31 + m_y) 
			Next
		Next
							
	End Method
	
End Type

Type CMouse
	Field m_x:Int, m_y:Int;
	Field m_slot:CSlot;
	Field m_columns:Int, m_rows:Int;
	
	Function Create:CMouse(x:Int, y:Int, columns:Int, rows:Int) 
		Local mouse:CMouse = New CMouse;
		mouse.m_x = x;
		mouse.m_y = y;
		mouse.m_columns = columns;
		mouse.m_rows = rows;
		mouse.createSlots() ;
		entity_list.AddLast(mouse) ;
		return mouse;
	End Function
	
	Method createSlots() 
		For Local columns:Int = 0 Until m_columns
			For Local rows:Int = 0 Until m_rows
				m_slot = CSlot.Create(columns * 31 + m_x, rows * 31 + m_y, 150, 150, 150) ;
			Next
		Next
	End Method
	
	Method Draw() 
	
		m_x = MouseX() ;
		m_y = MouseY() ;
	 
		For Local columns:Int = 0 Until m_columns
			For Local rows:Int = 0 Until m_rows
			
				m_slot.Draw(columns * 31 + m_x, rows * 31 + m_y) 

			Next
		Next
				
	End Method
	
End Type

Graphics(800, 600);

Global entity_list:TList = New TList;
Global slot_list:TList = New TList;

Local inventory:CInventory = CInventory.Create(50, 50, 5, 5) ;

Local mouse:CMouse = CMouse.Create(MouseX(), MouseY(), 2, 3) ;

'MoveMouse(300, 300) ;

While Not KeyHit(KEY_ESCAPE)
	Cls

	SortList(entity_list) ;
	inventory.Draw() ;
	mouse.Draw() ;

	Flip
Wend
End



Dreamora(Posted 2008) [#2]
The main problem comes from the fact that you:

1. Did not modularize it. You check for stuff all over the place. Above that it does not seem to be thought out at all. You have a draw that should be basing on m_x, m_y, yet you still send positions there -> defeats the point of storing anything within.

2. you only draw a single cell actually. You always draw m_slot ... you do not iterate through the slots ... your approach with the outer loops is for arrays but the handling is list ... thats "bullshit"
Either put it in an array and use the outer 2 loops or use a single loop over the list.

3. Dont see why you use manual rect collision as you know that the inventory won't move you can build a whole layer of static data that never needs to be cleared and rewritten ... thats several worlds faster than twin loops of math collision.

below code works but isn't the "cleanest" ... was a quick hack to yours only

SuperStrict

Type CSlot
	Field m_ID:Int;
	Field m_x:Int, m_y:Int;
	Field m_red:Int, m_green:Int, m_blue:Int;
	Field m_mouseSelected:Int = False;
	Field m_hover:Int = False;
	
	Field collision:Int = False
	
	Function Create:CSlot(x:Int, y:Int, red:Int, green:Int, blue:Int,list:TList)
		Local slot:CSlot = New CSlot;
		slot.m_x = x;
		slot.m_y = y;
		slot.m_red = red;
		slot.m_green = green;
		slot.m_blue = blue;
		list.AddLast(slot) ;
		Return slot;
	End Function
	
	Method changeColor(red:Int, green:Int, blue:Int) 
		Self.m_red = red;
		Self.m_green = green;
		Self.m_blue = blue;
	End Method

	Method Draw(x:Int, y:Int) 

						
		DrawText(Self.m_x+x, Self.m_x+x, Self.m_y+y + 30) ;
		DrawText(Self.m_y+y, Self.m_x+x + 30, Self.m_y+y + 30) ;
		
		If Self.collision
			Self.changeColor(255, 255, 255) ;
		Else
			Self.changeColor(150, 150, 150) ;
		EndIf
		
		SetColor(m_red, m_green, m_blue) ;
		DrawRect(Self.m_x+x, Self.m_y+y, 30, 30) ;
		
		If Self.collision
			SetColor(255, 0, 0) ;
			DrawText("C", m_x+x + 10, m_y+y + 10) ;
		EndIf
			
	End Method
	
End Type

Type CInventory
	Field m_x:Int, m_y:Int;
	Field m_slot:CSlot;
	Field m_columns:Int, m_rows:Int;
	
	Field inventorySlotList:TList = New TList
	
	Function Create:CInventory(x:Int, y:Int, columns:Int, rows:Int)
		Local inv:CInventory = New CInventory;
		inv.m_x = x;
		inv.m_y = y;
		inv.m_columns = columns;
		inv.m_rows = rows;
		inv.createSlots(inv.inventorySlotList);
		
		entity_list.AddLast(inv) ;
		Return inv;
	End Function
	
	Method createSlots(list:TList)
 
		For Local columns:Int = 0 Until m_columns
			For Local rows:Int = 0 Until m_rows
				m_slot = CSlot.Create(columns * 31 + m_x, rows * 31 + m_y, 150, 150, 150,list) ;
				CollideRect(m_slot.m_x,m_slot.m_y,30,30,0,COLLISION_LAYER_30,m_slot)
			Next
		Next
	End Method
	
	Method Draw(x:Int, y:Int) 
		
		For m_slot = EachIn inventorySlotList
			m_slot.Draw(x, y) 
		Next
							
	End Method
	
	Method resetCollision()
		For Local t:cslot = EachIn inventorySlotList
			t.collision = False
		Next
	End Method

	
End Type

Type CMouse
	Field m_x:Int, m_y:Int;
	Field m_slot:CSlot;
	Field m_columns:Int, m_rows:Int;
	
	Field mouseSlotList:TList = New TList
	
	Function Create:CMouse(x:Int, y:Int, columns:Int, rows:Int) 
		Local mouse:CMouse = New CMouse;
		mouse.m_x = x;
		mouse.m_y = y;
		mouse.m_columns = columns;
		mouse.m_rows = rows;
		mouse.createSlots(mouse.mouseSlotList) ;
		entity_list.AddLast(mouse) ;
		Return mouse;
	End Function
	
	Method createSlots(list:TList) 
		For Local columns:Int = 0 Until m_columns
			For Local rows:Int = 0 Until m_rows
				m_slot = CSlot.Create(columns * 31 + m_x, rows * 31 + m_y, 150, 150, 150,list) ;
			Next
		Next
	End Method
	
	Method Draw(x:Int, y:Int) 

		For m_slot = EachIn mouseSlotList
			m_slot.Draw(x,y) 
		Next
				
	End Method
	
	Method collide:Int(inventory:cinventory)
		inventory.resetCollision()
    	Local slot:cslot, col:Object[]
		For slot = EachIn mouseSlotList
			slot.collision = False
			col = CollideRect(slot.m_x+MouseX(), slot.m_y+MouseY(), 30, 30, COLLISION_LAYER_30, 0 )
			
			If col <> Null
				slot.collision = True
				'DebugStop
				Local slot2:cslot
				For slot2 = EachIn col
					slot2.collision = True
					
				Next
			EndIf	
		Next
		
		
	End Method
	
End Type

Graphics(800, 600);

Global entity_list:TList = New TList;
Global slot_list:TList = New TList;

Local inventory:CInventory = CInventory.Create(50, 50, 5, 5) ;

Local mouse:CMouse = CMouse.Create(0, 0, 2, 3) ;

MoveMouse(300, 300) ;

While Not KeyHit(KEY_ESCAPE)
	Cls

	mouse.collide(inventory)
	inventory.Draw(0,0) ;
	mouse.Draw(MouseX(), MouseY()) ;

	Flip
Wend
End