Any of you pro's keen on sharing some management secrets?

I'm probably going to poke around with my failure a little bit longer in an attempt to fix the bug. But incase of the inevitable, could very much use some how-to tips.
Code: Select all
Case 3 ;-Select Image Folder
If ReadFile(0, "MoBlur Temp.tmp") ;For some reason CreatePreferences() wouldn't overwrite, so I added this.
CloseFile(0)
DeleteFile("MoBlur Temp.tmp")
EndIf
If CreatePreferences("MoBlur Temp.tmp")
SetFileAttributes("MoBlur Temp.tmp", #PB_FileSystem_Hidden) ;Windows only
InitialPath$ = "C:\"
InputImages$ = PathRequester("Load images...", InitialPath$)
SetGadgetText(2, InputImages$)
ImageCount = 0
StatusBarText(10, 0, "Wait! Counting Images") ;counts too fast for this to be seen but just in case
ExamineDirectory(0, InputImages$, "*.png")
While NextDirectoryEntry(0) ;getting the total number of images
ImageCount +1
Wend
Haha, yeah I always try to add as many comments as I can because I have a habit of forgetting what something does.J. Baker wrote:I comment ";" (without quotes) almost everything. Usually so I remember why I added that line. It helps when going back to code you wrote some time ago. And don't forget the ";-" (without quotes) when commenting on larger sections of your code. That will add it to the right column in PB under procedures list. Hope that helps.
Code: Select all
; --------------------------------------------------------------------------
; last modified: June 29th, 2011 @ 10:40:53 PM
; --------------------------------------------------------------------------
Enumeration
#FLAG_RESET = 0
#NETWORK_HEARTBEAT = 1
#NETWORK_CONNECT = 2 ;
#KEYINPUT_LEFT = 4
#KEYINPUT_RIGHT = 8
#KEYINPUT_UP = 16
#KEYINPUT_DOWN = 32
#KEYINPUT_FIRE = 64
#HEARTBEAT_TIMEOUT_COUNT = 5
#HEARTBEAT_TIMER = 1000
EndEnumeration
Global *bufSend = AllocateMemory(1024)
Global *__bufSend = AllocateMemory(5)
Global *bufRecv = AllocateMemory(1024)
Structure pdata
id.l
hbcount.b
x.f
y.f
keyLeft.b
keyRight.b
keyUp.b
keyDown.b
bitFlag.b
name.s{20}
EndStructure
Structure cdata
heartbeat.s{4}
id.l
keyFlag.b
x.f
y.f
name.s{20}
EndStructure
Global Dim PlayerData.pdata(0) ; if client, element zero is always the player
Global gameType.l = 0, host.l
Declare client_ProcessData()
Declare server_ProcessData()
Declare client_GetInput()
Declare client_RecvData()
Declare client_SendData()
Declare server_RecvData()
Declare server_SendData()
Enumeration
#MAIN_WIN
EndEnumeration
InitNetwork() : InitSprite() : InitKeyboard()
gameType.l = Val(InputRequester("GAMETYPE", "Run as Client or Server? (enter 0 for client or 1 for server)", "0"))
OpenWindow(#MAIN_WIN, 0, 0, 800, 600, "Test", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
OpenWindowedScreen(WindowID(#MAIN_WIN), 0, 0, 800, 600, 1, 0, 0)
#Player = 0 ; <-- remove.. V -- remove..
CreateSprite(#Player, 50, 50, #PB_Sprite_Texture | #PB_Sprite_AlphaBlending)
StartDrawing(SpriteOutput(#Player))
Box(0, 0, 50, 50, RGB(0,50,255))
StopDrawing()
If gameType.l = 0 ;{
SetWindowTitle(#MAIN_WIN, "Client")
port.l = Val(InputRequester("Choose port...", "Input an open UDP port", "21000"))
host.l = OpenNetworkConnection(InputRequester("Choose IP...", "Input the IP address to connect to", "127.0.0.1"), port.l, #PB_Network_UDP)
SendNetworkString(host.l, "cn")
PlayerData(0)\id = 0
Else
SetWindowTitle(#MAIN_WIN, "Server")
port.l = Val(InputRequester("Choose port...", "Input an open UDP port", "21000"))
host.l = CreateNetworkServer(#PB_Any, port.l, #PB_Network_UDP)
OpenConsole()
EndIf ;}
Repeat
Delay(1)
eventID = WaitWindowEvent(1)
If gameType.l = 0 ; quick hack to do some position updating/heartbeats should probably throw this into a neatly packed procedure
client_GetInput()
client_RecvData()
If netClientHeartBeatTimer < ElapsedMilliseconds() ; send heartbeat...
SendNetworkString(host.l, "hb")
PlayerData(0)\hbcount + 1
If PlayerData(0)\hbcount >= #HEARTBEAT_TIMEOUT_COUNT
MessageRequester("Error","Lost connection to the server")
End
EndIf
netClientHeartBeatTimer = ElapsedMilliseconds() + #HEARTBEAT_TIMER
EndIf
client_SendData()
; client side position updating
For x = 0 To ArraySize(PlayerData())
If (PlayerData(x)\bitFlag & #KEYINPUT_LEFT) <> 0 : PlayerData(x)\x = PlayerData(x)\x - 1 : EndIf
If (PlayerData(x)\bitFlag & #KEYINPUT_RIGHT) <> 0 : PlayerData(x)\x = PlayerData(x)\x + 1 : EndIf
If (PlayerData(x)\bitFlag & #KEYINPUT_UP) <> 0 : PlayerData(x)\y = PlayerData(x)\y - 1 : EndIf
If (PlayerData(x)\bitFlag & #KEYINPUT_DOWN) <> 0 : PlayerData(x)\y = PlayerData(x)\y + 1 : EndIf
Next x
ElseIf gameType.l = 1
server_RecvData()
If netServerHeartBeatTimer < ElapsedMilliseconds()
;PrintN("[netHeartBeat] netHeartBeatTimer has elapsed, doing a row call to see who's here.")
For cn = 0 To ArraySize(PlayerData()) ; update heartbeat count and check for disconnections
If PlayerData(cn)\id <> 0
If PlayerData(cn)\hbcount >= #HEARTBEAT_TIMEOUT_COUNT
PrintN("[netHeartBeat] [ID: "+Str(PlayerData(cn)\id)+"] lost connection, removing id for recycling...")
PlayerData(cn)\id = 0
Else
PlayerData(cn)\hbcount + 1; add to the count...
EndIf
EndIf
Next cn
netServerHeartBeatTimer = ElapsedMilliseconds() + #HEARTBEAT_TIMER
EndIf
; Do some position x/y updating.
For cn = 0 To ArraySize(PlayerData())
If PlayerData(cn)\id <> 0
If PlayerData(cn)\keyLeft = #KEYINPUT_LEFT : PlayerData(cn)\x = PlayerData(cn)\x - 1 : EndIf
If PlayerData(cn)\keyRight = #KEYINPUT_RIGHT : PlayerData(cn)\x = PlayerData(cn)\x + 1 : EndIf
If PlayerData(cn)\keyUp = #KEYINPUT_UP : PlayerData(cn)\y = PlayerData(cn)\y - 1 : EndIf
If PlayerData(cn)\keyDown = #KEYINPUT_DOWN : PlayerData(cn)\y = PlayerData(cn)\y + 1 : EndIf
EndIf
Next cn
EndIf
ClearScreen(RGB(0,0,0))
For x = 0 To ArraySize(PlayerData())
If PlayerData(x)\id <> 0
DisplaySprite(#Player, PlayerData(x)\x, PlayerData(x)\y)
EndIf
Next x
FlipBuffers()
Until eventID = #PB_Event_CloseWindow
Procedure client_GetInput()
Static keyLeftState.b, keyRightState.b, keyUpState.b, keyDownState.b
Shared keyFlagLeft.b, keyFlagRight.b, keyFlagUp.b, keyFlagDown.b
Shared netBitFlag.b
ExamineKeyboard()
; on keypress set the keyflag state for the bit calculation later.
If KeyboardPushed(#PB_Key_A)
If keyLeftState.b = 0 : keyFlagLeft.b = #KEYINPUT_LEFT : keyLeftState.b = 1 : EndIf
Else
If keyLeftState.b = 1 : keyFlagLeft.b = #FLAG_RESET : keyLeftState.b = 0 : EndIf
EndIf
If KeyboardPushed(#PB_Key_D)
If keyRightState.b = 0 : keyFlagRight.b = #KEYINPUT_RIGHT : keyRightState.b = 1 : EndIf
Else
If keyRightState.b = 1 : keyFlagRight.b = #FLAG_RESET : keyRightState.b = 0 : EndIf
EndIf
If KeyboardPushed(#PB_Key_W)
If keyUpState.b = 0 : keyFlagUp.b = #KEYINPUT_UP : keyUpState.b = 1 : EndIf
Else
If keyUpState.b = 1 : keyFlagUp = #FLAG_RESET : keyUpState.b = 0 : EndIf
EndIf
If KeyboardPushed(#PB_Key_S)
If keyDownState.b = 0 : keyFlagDown.b = #KEYINPUT_DOWN : keyDownState.b = 1 : EndIf
Else
If keyDownState.b = 1 : keyFlagDown.b = #FLAG_RESET : keyDownState.b = 0 : EndIf
EndIf
EndProcedure
Procedure client_SendData()
Shared keyFlagLeft.b, keyFlagRight.b, keyFlagUp.b, keyFlagDown.b
Shared netBitFlag.b
Static __newBitFlag.b
; form bit calc, can store several instructions in a single byte.
netBitFlag.b = keyFlagLeft.b|keyFlagRight.b|keyFlagUp.b|keyFlagDown.b;|#NETWORK_HEARTBEAT
; should only send when a change occurs...
If netBitFlag.b <> __newBitFlag.b ; checking if a change has occured from a key press.
Debug "Before sending: " + Str(netBitFlag.b)
PokeB(*bufSend + 4, netBitFlag.b)
SendNetworkData(host.l, *bufSend, SizeOf(cdata))
__newBitFlag.b = netBitFlag.b
EndIf
EndProcedure
Procedure client_RecvData()
eventNetwork= NetworkClientEvent(host.l)
If eventNetwork
Select eventNetwork
Case #PB_NetworkEvent_Data
recv = ReceiveNetworkData(host.l, *bufRecv, SizeOf(cdata))
;Debug "client BitFlag = " + Str(PeekB(*bufRecv))
If recv > 0
client_ProcessData()
EndIf
EndSelect
EndIf
EndProcedure
Procedure client_ProcessData()
If PeekS(*bufRecv) = "hb"
;Debug "[netHeartBeat] received heartbeat reply from server.. Reseting hbcount"
PlayerData(0)\hbcount = 0
EndIf
If FindString(PeekS(*bufRecv), "c|", 0)
Debug "Resizing array: " + Mid(PeekS(*bufRecv),FindString(PeekS(*bufRecv), "c|", 0))
ReDim PlayerData(Val(Mid(PeekS(*bufRecv),FindString(PeekS(*bufRecv), "c|", 0))))
EndIf
;Else
For x = 0 To ArraySize(PlayerData()) ; try to update all clients found in the server.... fails....
; why is this pretending that there are more than 1 client in the server if only 1 client is running..?
Debug "[ID: " + Str(PeekL(*bufRecv+4)) + "] Attempting to match"
If PlayerData(x)\id = PeekL(*bufRecv + 4) ; Do an update for clients we know already exist
;Debug "Matched id's with received ID...."
PlayerData(x)\bitFlag = PeekB(*bufRecv + 8) ; bitflag
PlayerData(x)\x = PeekF(*bufRecv + 9) ; struct\y
PlayerData(x)\y = PeekF(*bufRecv + 13) ; struct\y
PlayerData(x)\name = PeekS(*bufSend + 17) ; struct\name.s{20}
Debug "[ID: "+Str(PlayerData(x)\id)+"] [X: " +Str(PlayerData(x)\x) + "] [Y:"+Str(PlayerData(x)\y) + "] Already Exists"
EndIf
If x = ArraySize(PlayerData())
;If PlayerData(x)\id = 0
PlayerData(x)\id = PeekL(*bufRecv + 4)
PlayerData(x)\bitFlag = PeekB(*bufRecv + 8) ; bitflag
PlayerData(x)\x = PeekF(*bufRecv + 9) ; struct\y
PlayerData(x)\y = PeekF(*bufRecv + 13) ; struct\y
PlayerData(x)\name = PeekS(*bufSend + 17) ; struct\name.s{20}
Debug "[ID: "+Str(PlayerData(x)\id)+"] [X: " +Str(PlayerData(x)\x) + "] [Y:"+Str(PlayerData(x)\y) + "] New Element"
;EndIf
EndIf
Next x
;EndIf
EndProcedure
Procedure server_RecvData()
Shared clientID
eventNetwork = NetworkServerEvent()
If eventNetwork
clientID = EventClient()
Select eventNetwork
Case #PB_NetworkEvent_Data
recv = ReceiveNetworkData(clientID, *bufRecv, SizeOf(cdata))
PrintN("[netReceive] [IP: " + IPString(GetClientIP(clientID)) + "] Buffer content: " + Str(PeekB(*bufRecv)))
If recv > 0
server_ProcessData()
EndIf
EndSelect
EndIf
EndProcedure
Procedure server_ProcessData()
Shared clientID
Static netRecycle
;
If PeekS(*bufRecv) = "hb" ; Heartbeat
PrintN("[netHeartBeat] received a heartbeat [clientID:"+Str(clientID)+"]")
For cn = 0 To ArraySize(PlayerData())
If PlayerData(cn)\id = clientID
;PrintN("[netHeartBeat] heartbeat matched [clientID:"+Str(clientID)+" @ "+Str(cn)+"]")
PlayerData(cn)\hbcount.b = 0
SendNetworkString(PlayerData(cn)\id, "hb")
;PrintN("[netHeartbeat] sent a heartbeat back to client. We're here!!!")
Break
EndIf
Next cn
EndIf
If PeekS(*bufRecv) = "cn";(PeekB(*bufRecv) & #NETWORK_CONNECT) <> 0 ; process any connection attempts
; TODO: check if max connections reached before continuing
PrintN("[netConnect] received connection attempt..")
For cn = 0 To ArraySize(PlayerData())
If PlayerData(cn)\id = clientID ; player already in the server!
PrintN("[netConnect] player already connected!")
Break
EndIf
If cn = ArraySize(PlayerData()) ; reached the end of the array with no matches. he's legit.
PrintN("[netConnect] id was not found.. ")
If PlayerData(cn)\id = 0 ; check if last element is empty
;PrintN("[netConnect] current array["+Str(cn)+"] was empty, no need to recycle.")
PlayerData(cn)\id = clientID
PrintN("[netConnect] player["+Str(cn)+"] joined successfully.")
For x = 0 To ArraySize(PlayerData())
SendNetworkString(PlayerData(cn)\id, "c|"+Str(ArraySize(PlayerData())))
Next x
Break
Else
netRecycle = #False
For c = 0 To ArraySize(PlayerData()) ; recycle empty elements
;PrintN("[netConnect] attempting to recycle..")
If PlayerData(c)\id = 0
;PrintN("[netConnect] found empty slot, adding id to array and continuing...")
netRecycle = #True
PlayerData(c)\id = clientID
PrintN("[netConnect] player["+Str(cn)+"] joined successfully.")
For x = 0 To ArraySize(PlayerData())
SendNetworkString(PlayerData(cn)\id, "c|"+Str(ArraySize(PlayerData())))
Next x
Break
EndIf
Next c
If netRecycle = #False
;PrintN("[netConnect] recycling failed, resizing array.")
ReDim PlayerData.pdata(ArraySize(PlayerData())+1) ; resize
PrintN("[netConnect] player["+Str(cn)+"] joined successfully.")
For x = 0 To ArraySize(PlayerData())
SendNetworkString(PlayerData(cn)\id, "c|"+Str(ArraySize(PlayerData())))
Next x
PlayerData(cn+1)\id = clientID
Break
EndIf
EndIf
EndIf
Next cn
EndIf
; TODO: bit flag check should be optimized some how..
If (PeekB(*bufRecv + 4) & #KEYINPUT_LEFT) <> 0
For kz = 0 To ArraySize(PlayerData())
If PlayerData(kz)\id = clientID : PlayerData(kz)\keyLeft = #KEYINPUT_LEFT : EndIf
Next kz
Else
For kz = 0 To ArraySize(PlayerData())
If PlayerData(kz)\id = clientID : PlayerData(kz)\keyLeft = #FLAG_RESET : EndIf
Next kz
EndIf
If (PeekB(*bufRecv + 4) & #KEYINPUT_RIGHT) <> 0
For kz = 0 To ArraySize(PlayerData())
If PlayerData(kz)\id = clientID : PlayerData(kz)\keyRight = #KEYINPUT_RIGHT : EndIf
Next kz
Else
For kz = 0 To ArraySize(PlayerData())
If PlayerData(kz)\id = clientID : PlayerData(kz)\keyRight = #FLAG_RESET : EndIf
Next kz
EndIf
If (PeekB(*bufRecv + 4) & #KEYINPUT_UP) <> 0
For kz = 0 To ArraySize(PlayerData())
If PlayerData(kz)\id = clientID : PlayerData(kz)\keyUp = #KEYINPUT_UP : EndIf
Next kz
Else
For kz = 0 To ArraySize(PlayerData())
If PlayerData(kz)\id = clientID : PlayerData(kz)\keyUp = #FLAG_RESET : EndIf
Next kz
EndIf
If (PeekB(*bufRecv + 4) & #KEYINPUT_DOWN) <> 0
For kz = 0 To ArraySize(PlayerData())
If PlayerData(kz)\id = clientID : PlayerData(kz)\keyDown = #KEYINPUT_DOWN : EndIf
Next kz
Else
For kz = 0 To ArraySize(PlayerData())
If PlayerData(kz)\id = clientID : PlayerData(kz)\keyDown = #FLAG_RESET : EndIf
Next kz
EndIf
server_SendData()
EndProcedure
Procedure server_SendData() ; should only use this function after some event occurs...
Shared clientID
Static *struct.cdata
; TODO: need to only send data when a client structure has changed. probably don't need to include x/y until after bitFlag & key <> 0
; probably need to look into a way of comparing memory of each client..
*struct.cdata = AllocateMemory(SizeOf(cdata))
For y = 0 To ArraySize(PlayerData()) ; <- client to send data to
For x = 0 To ArraySize(PlayerData())
With *struct
\heartbeat = "hb"
\keyFlag = PlayerData(x)\keyDown | PlayerData(x)\keyLeft | PlayerData(x)\keyRight | PlayerData(x)\keyUp
;If PlayerData(y)\id = PlayerData(x)\id
; \id = -1 ; -1 = local client id, or the id that belongs to playerdata(0) on the client side -- no longer true
;Else
\id = PlayerData(x)\id
;EndIf
\x = PlayerData(x)\x
\y = PlayerData(x)\y
Debug "["+Str(PlayerData(x)\id)+"] [X: " +Str(PlayerData(x)\x) + "] [Y:"+Str(PlayerData(x)\y) + "]"
EndWith
SendNetworkData(PlayerData(y)\id, *struct, SizeOf(cdata))
Next x
Next y
EndProcedure
Use OOP! It's the best way of handling complexity, but because PB is not an object orientated language, it's not really an option so dispite the lack of OOP in PB, try these:Nituvious wrote:I just turned a very nice start of a project into a "omg i need to rewrite it again" project. I think it was due to trying to fix some bugs...
Any of you pro's keen on sharing some management secrets?![]()
I'm probably going to poke around with my failure a little bit longer in an attempt to fix the bug. But incase of the inevitable, could very much use some how-to tips.
Please god don't do this, that's insane!!! Use a proper revision control system such as Mercurial its easy to use and FREE! Honestly J. Baker you are doing manually what a revision control system does for you! Using a revision control system you can roll back any file to any previous state at any time of development!J. Baker wrote:Been there, done that. I also will save a working version as I go. Like each PB Source File has it own version number, gametest_1.pb, gametest_2.pb, gametest_3.pb. Just so I can fall back on the previous file and try again.
Thanks but I'm fine with the way I do things.Blood wrote:Please god don't do this, that's insane!!! Use a proper revision control system such as Mercurial its easy to use and FREE! Honestly J. Baker you are doing manually what a revision control system does for you! Using a revision control system you can roll back any file to any previous state at any time of development!
i find git is harder to use than mercurial, but each to his own.RichAlgeni wrote:I agree with Blood, find a good source code management program and it will make your life so much easier!
Here's another in case anyone is interested:
http://code.google.com/p/msysgit