none
HELP! I can't make my tank fire properly! RRS feed

  • Question

  • SBV652-2 (Ignore The username stuff) no matter what i do I can't make it fire properly! It always locks up and bogs down. can anyone help?

    Thanks in advance!


    One thing that is impossible is impossible no matter if it is proven so first.

    Monday, August 27, 2012 2:38 AM
    Answerer

Answers

  • You will find another problem - synchronicity - time delays in the commands for the different plays receiving and
     acting on commands.

    Example:

    Modified server.php here and import HGR615.  Make a copy reversing.

    Local = 1
    Remote = 2

    to

    Local = 2
    Remote = 1

    Compile both and run both from command line and use Up and Down arrow keys to test.

    EDIT

    A possible solution, PRD185

    Monday, August 27, 2012 8:29 PM
    Moderator
  • Which extension are you using for the Timer - it conflicts with the native SmallBasic version - perhaps it should be re-named something other than Timer, with a prefix like the FC extensions all prefixed with FC.

    Can you create a version that shows the problem without the network bits - all I get is an orange screen perhaps due to your bandwidth being exceeded so no images.

    Also, looking at the code there is only tank movement (some optimization of this code is possible - but not your issue I think) - and no code to fire.

    I guess the approach is to test the network server bits separately from the movement gameplay, keeping it very simple with just one key for example to test, then add all the movement and other gameplay when the core works well.

    So, I suggest a very short simple code that has only the key features, i.e. sever networked key entry with interaction on the GraphicsWindow. 

    EDIT

    For anyone else helping, this what I could see - the steps I went through:

    Some checking for valid returns or server response may be needed - also the necessary setup for someone to test, your server/server.php which can be run using wamp, IIS or similar, tested using localhost.

    I replaced the AskUsername with:

    Sub AskUsername
      Username = Text.ConvertToUpperCase("Player1")
      EUsername = Text.ConvertToUpperCase("Player2")
      IP = "localhost"
      TextWindow.Hide()
      Playernum = 1
      EPlayernum = 2
    EndSub

    This gives:

    http://localhost/server/server.php?program=PLAYER1&x=&y=&Z=

    When I do this in FF, I get:

    PHP Warning:  fopen(data.txt) [<a href='function.fopen'>function.fopen</a>]: failed to open stream: Permission denied in C:\inetpub\wwwroot\server\server.php on line 68

    So change permissions here, then I get:

    prog1x=1;prog1y=2;prog1Z=3;ZOCKx=Down;ZOCKy=218;ZOCKZ=524;FAMBACKx=Right;FAMBACKy=376;FAMBACKZ=1405906;

    OK, all good, except that the variable names seem to be prefixed by ZOCK and FAMBACK.

    When I look further:

      url= "http://" + IP + "/server/server.php?program="+Username+"&x="+Key+"&y="+ Y + "&Z=" + X  'Sends data
      data = Network.GetWebPageContents(url) 'Gets data
      TextWindow.WriteLine(data)
      TextWindow.WriteLine(EUsername)
      TextWindow.WriteLine(data[EUsername + "x"])

    I get EUsername = "PLAYER2" and therefore data[EUsername + "x"] doesn't exist.

    So I change user names to these, noting the Z seem to be upper case and the x,y lower case - may be an issue later.

    Sub AskUsername
      Username = Text.ConvertToUpperCase("Zock")
      EUsername = Text.ConvertToUpperCase("Famback")
      IP = "localhost"
      TextWindow.Hide()
      Playernum = 1
      EPlayernum = 2
    EndSub

    So I think the php logic needs to be checked carefully, or at least its functionality (API) explained clearly so we know exactly what is supposed to do.

    Also, it would be easier if you had sent the SmallBasic code set up like this - hard for anyone to help if they have to go through this first.

    So now I get a return from the server, I have no images for the tanks and no fire that I can see, so that's as far as I can go.  The logic for handling the buttons is rather complex - since you have the key names you don't need loads of subroutines handling each individually.

    However, I like the idea of a simple php to handle server control over a home or web network (Perhaps writing an API spec for this php will help you and others using/testing it) - keep at it.

    MORE - a bit roundabout but commented as I tried stuff and get to figure out what it is doing

    The return in data looks like this, depending on user names set:

    prog1x=1;prog1y=2;prog1Z=3;ZOCKx=;ZOCKy=;ZOCKZ=;FAMBACKx=Right;FAMBACKy=376;FAMBACKZ=1405906;PLAYER1x=;PLAYER1y=60;PLAYER1Z=480;

    Notice that element 4 (ZOCKx) has no value after the =.  SmallBasic then doesn't find the array elements after this, in fact 'TextWindow.WriteLine(Array.GetItemCount(data))' returns 3 and therefore data[PLAYER1x] is undefined.

    I now see the data file created by the php and the ZOCK and FAMBACK are just your previous entries, I don't see an entry created for EUsername, my original "Player2" as used in Sub Get_Assign_X_Y.

    I returned to Player1 and Player2 and deleted the php data file.  This failed, so I just deleted the contents of data.txt and got:

    Zock77x=1;Zock77y=2;Zock77Z=3;PLAYER1x=;PLAYER1y=;PLAYER1Z=;

    No Player2 and Player1 values with no values.  This is because, KEY, x and z are not set on the first call - the php should handle this since the empty values cause a problem truncating the array:

    url= "http://" + IP + "/server/server.php?program="+Username+"&x="+Key+"&y="+ Y + "&Z=" + X

    So change this to (EUsername not Username):

    url= "http://" + IP + "/server/server.php?program="+EUsername+"&x="+Key+"&y="+ Y + "&Z=" + X

    This now works on all calls when a key is pressed, storing the key and its coordinates.

    Monday, August 27, 2012 9:48 AM
    Moderator
  • <?php
    	$dataFile = "data.txt";
    	$id = "program";
    
    	// Step 1: Read the current data file, convert back into a structure
    	readData();
    	// Step 2: Update the data, as commanded and Wite it out
    	// Step 3: If changed, then also Lock the data file so we can safely write to it.  Then write our data, unlock, and close
    	updateData();
    	// Step 4: Loop through each id, and print its data
    	printData();
    
    function readData()
    {
    	global $data, $dataFile;
    	if (!file_exists($dataFile))						// Create if it doesn't exist
    	{
    		$handle = fopen($dataFile,"w");
    		fwrite($handle,"", 0);
    		fclose($handle);
    	}
    	$handle = fopen($dataFile,"r");			// Open
    	while(!flock($handle,LOCK_SH))			// Lock
    	{	
    		sleep(1);
    	}
    	$data_file = fread($handle,2000);		// Read
    	flock($handle, LOCK_UN);						// Unlock
    	fclose($handle);										// Close
    	$data = unserialize($data_file);
    }
    
    function updateData()
    {
    	global $data, $id;
    	$keys = array_keys($_GET);
    	if ($keys[0] == $id)
    	{
    		$element = array();
    		foreach ($keys as &$key)
    		{
    			if ($_GET[$key] == "") $_GET[$key] = "-1"; //A null values isn't allowed
    			$element[$key] = $_GET[$key];
    		}
    
    		if (is_array($data))
    		{
    			$found = 0;
    			foreach ($data as &$entry)
    			{
    				if ($entry[$id] == $element[$id])		//Replace entry
    				{
    					$entry=$element;
    					$found = 1;
    					break;
    				}
    			}
    			if ($found == 0)	array_push($data,$element);	//Add entry
    		}
    		else
    		{
    			$data = array($element);			//Fist entry
    		}
    		
    		writeData();
    	}
    }
    
    function writeData()
    {
    	global $data, $dataFile;
    	$handle = fopen($dataFile,"w");
    	while(!flock($handle,LOCK_EX))
    	{
    		sleep(1);
    	}
    	$data_string=serialize($data);											// Serialize
    	fwrite($handle,$data_string, strlen($data_string));	// Write
    	flock($handle,LOCK_UN);													// Unlock
    	fclose($handle);																	// Close
    }
    
    function printData()
    {
    	global $data, $id;
    	if (is_array($data))
    	{
    		foreach ($data as &$entry)
    		{
    			$keys = array_keys($entry);
    			if (is_array($keys))
    			{
    				echo $entry[$keys[0]]."=";
    				foreach ($keys as &$key)
    				{
    					if ($key != $keys[0])
    					{
    						echo $key."\=".$entry[$key]."\;";
    					}
    				}
    				echo ";";
    			}
    		}
    	}
    }
    
    ?>
    
    

    Monday, August 27, 2012 5:01 PM
    Moderator
  • With the modified script, we can run the programs (Player names reversed) and this works pretty well.

    Local = "Player1"
    remote = "Player2"
    GraphicsWindow.KeyDown = OnKeyDown
    
    While ("True")
      url="http://localhost/server/server.php?program="  'Gets data
      data = Network.GetWebPageContents(url)
      TextWindow.Clear()
      TextWindow.WriteLine(data[Local]["x"])
      TextWindow.WriteLine(data[Local]["y"])
      TextWindow.WriteLine(data[Local]["Z"])
      TextWindow.WriteLine(data[remote]["x"])
      TextWindow.WriteLine(data[remote]["y"])
      TextWindow.WriteLine(data[remote]["Z"])
      Program.Delay(100)
    EndWhile
    
    Sub OnKeyDown
      Key = GraphicsWindow.LastKey
      X = GraphicsWindow.MouseX
      Y = GraphicsWindow.MouseY
      url="http://localhost/server/server.php?program="+Local+"&x="+Key+"&y="+ Y + "&Z=" + X  'Sends data
      Network.GetWebPageContents(url)
    EndSub
    

    Good enough to start moving balls in the GraphicsWindow and then maybe firing things.  Perhaps also use x for x, y for y and key for key etc

    Monday, August 27, 2012 5:23 PM
    Moderator

All replies

  • Which extension are you using for the Timer - it conflicts with the native SmallBasic version - perhaps it should be re-named something other than Timer, with a prefix like the FC extensions all prefixed with FC.

    Can you create a version that shows the problem without the network bits - all I get is an orange screen perhaps due to your bandwidth being exceeded so no images.

    Also, looking at the code there is only tank movement (some optimization of this code is possible - but not your issue I think) - and no code to fire.

    I guess the approach is to test the network server bits separately from the movement gameplay, keeping it very simple with just one key for example to test, then add all the movement and other gameplay when the core works well.

    So, I suggest a very short simple code that has only the key features, i.e. sever networked key entry with interaction on the GraphicsWindow. 

    EDIT

    For anyone else helping, this what I could see - the steps I went through:

    Some checking for valid returns or server response may be needed - also the necessary setup for someone to test, your server/server.php which can be run using wamp, IIS or similar, tested using localhost.

    I replaced the AskUsername with:

    Sub AskUsername
      Username = Text.ConvertToUpperCase("Player1")
      EUsername = Text.ConvertToUpperCase("Player2")
      IP = "localhost"
      TextWindow.Hide()
      Playernum = 1
      EPlayernum = 2
    EndSub

    This gives:

    http://localhost/server/server.php?program=PLAYER1&x=&y=&Z=

    When I do this in FF, I get:

    PHP Warning:  fopen(data.txt) [<a href='function.fopen'>function.fopen</a>]: failed to open stream: Permission denied in C:\inetpub\wwwroot\server\server.php on line 68

    So change permissions here, then I get:

    prog1x=1;prog1y=2;prog1Z=3;ZOCKx=Down;ZOCKy=218;ZOCKZ=524;FAMBACKx=Right;FAMBACKy=376;FAMBACKZ=1405906;

    OK, all good, except that the variable names seem to be prefixed by ZOCK and FAMBACK.

    When I look further:

      url= "http://" + IP + "/server/server.php?program="+Username+"&x="+Key+"&y="+ Y + "&Z=" + X  'Sends data
      data = Network.GetWebPageContents(url) 'Gets data
      TextWindow.WriteLine(data)
      TextWindow.WriteLine(EUsername)
      TextWindow.WriteLine(data[EUsername + "x"])

    I get EUsername = "PLAYER2" and therefore data[EUsername + "x"] doesn't exist.

    So I change user names to these, noting the Z seem to be upper case and the x,y lower case - may be an issue later.

    Sub AskUsername
      Username = Text.ConvertToUpperCase("Zock")
      EUsername = Text.ConvertToUpperCase("Famback")
      IP = "localhost"
      TextWindow.Hide()
      Playernum = 1
      EPlayernum = 2
    EndSub

    So I think the php logic needs to be checked carefully, or at least its functionality (API) explained clearly so we know exactly what is supposed to do.

    Also, it would be easier if you had sent the SmallBasic code set up like this - hard for anyone to help if they have to go through this first.

    So now I get a return from the server, I have no images for the tanks and no fire that I can see, so that's as far as I can go.  The logic for handling the buttons is rather complex - since you have the key names you don't need loads of subroutines handling each individually.

    However, I like the idea of a simple php to handle server control over a home or web network (Perhaps writing an API spec for this php will help you and others using/testing it) - keep at it.

    MORE - a bit roundabout but commented as I tried stuff and get to figure out what it is doing

    The return in data looks like this, depending on user names set:

    prog1x=1;prog1y=2;prog1Z=3;ZOCKx=;ZOCKy=;ZOCKZ=;FAMBACKx=Right;FAMBACKy=376;FAMBACKZ=1405906;PLAYER1x=;PLAYER1y=60;PLAYER1Z=480;

    Notice that element 4 (ZOCKx) has no value after the =.  SmallBasic then doesn't find the array elements after this, in fact 'TextWindow.WriteLine(Array.GetItemCount(data))' returns 3 and therefore data[PLAYER1x] is undefined.

    I now see the data file created by the php and the ZOCK and FAMBACK are just your previous entries, I don't see an entry created for EUsername, my original "Player2" as used in Sub Get_Assign_X_Y.

    I returned to Player1 and Player2 and deleted the php data file.  This failed, so I just deleted the contents of data.txt and got:

    Zock77x=1;Zock77y=2;Zock77Z=3;PLAYER1x=;PLAYER1y=;PLAYER1Z=;

    No Player2 and Player1 values with no values.  This is because, KEY, x and z are not set on the first call - the php should handle this since the empty values cause a problem truncating the array:

    url= "http://" + IP + "/server/server.php?program="+Username+"&x="+Key+"&y="+ Y + "&Z=" + X

    So change this to (EUsername not Username):

    url= "http://" + IP + "/server/server.php?program="+EUsername+"&x="+Key+"&y="+ Y + "&Z=" + X

    This now works on all calls when a key is pressed, storing the key and its coordinates.

    Monday, August 27, 2012 9:48 AM
    Moderator
  • Oops...

    I think my computer (The host) was off. so that would enplane the network problem. (I likes throwing A error when the host is not on) That would be why things were not Registering. So try it now. Also, When you type the EUsername, It doesn't create it. it just uses it to get the other persons positions. As for the bandwidth being exceeded. would you like me to send you the pics?

    The fire sub I forgot to put in with the code I posted (Duh) so here it is. PZW702 Remember to change lines 96 - 101 to your pics.

    Thank you so much for replying!!


    One thing that is impossible is impossible no matter if it is proven so first.

    Monday, August 27, 2012 2:49 PM
    Answerer
  • I get no reply from:

    http://192.168.1.129/server/server.php?program=PLAYER1&x=&y=&Z=

    Can we separate the server from the gameplay and fire.

    We need a version that can be tested easily.

    I suggest using ellipses rather than images and using localhost rather than your IP.

    Your server.php outputs the previously stored data and not the currently added.

    For example if we run this and another smallbasic program with Player1 and Player2 reversed - both running at the same time from the command line.

    Local = "Player1"
    remote = "Player2"
    GraphicsWindow.KeyDown = OnKeyDown

    Sub OnKeyDown
      Key = GraphicsWindow.LastKey
      X = GraphicsWindow.MouseX
      Y = GraphicsWindow.MouseY
      url="http://localhost/server/server.php?program="+Local+"&x="+Key+"&y="+ Y + "&Z=" + X  'Sends data
      data = Network.GetWebPageContents(url)
      TextWindow.WriteLine(data[Local+"x"])
      TextWindow.WriteLine(data[Local+"y"])
      TextWindow.WriteLine(data[Local+"Z"])
      TextWindow.WriteLine(data[remote+"x"])
      TextWindow.WriteLine(data[remote+"y"])
      TextWindow.WriteLine(data[remote+"Z"])
    EndSub

    If you can run this and it behaves as you expect, then we can start adding simple gameplay.

    I modified your server.php to handle a few things like no data file present, handle arbitrary number of values x, y, z, status, score etc, return the current not last data and return it in a 2D array format data[Local]["X"].  If you want I can post this, it may help.

    Monday, August 27, 2012 4:49 PM
    Moderator
  • That would be great!

    One thing that is impossible is impossible no matter if it is proven so first.

    Monday, August 27, 2012 4:55 PM
    Answerer
  • <?php
    	$dataFile = "data.txt";
    	$id = "program";
    
    	// Step 1: Read the current data file, convert back into a structure
    	readData();
    	// Step 2: Update the data, as commanded and Wite it out
    	// Step 3: If changed, then also Lock the data file so we can safely write to it.  Then write our data, unlock, and close
    	updateData();
    	// Step 4: Loop through each id, and print its data
    	printData();
    
    function readData()
    {
    	global $data, $dataFile;
    	if (!file_exists($dataFile))						// Create if it doesn't exist
    	{
    		$handle = fopen($dataFile,"w");
    		fwrite($handle,"", 0);
    		fclose($handle);
    	}
    	$handle = fopen($dataFile,"r");			// Open
    	while(!flock($handle,LOCK_SH))			// Lock
    	{	
    		sleep(1);
    	}
    	$data_file = fread($handle,2000);		// Read
    	flock($handle, LOCK_UN);						// Unlock
    	fclose($handle);										// Close
    	$data = unserialize($data_file);
    }
    
    function updateData()
    {
    	global $data, $id;
    	$keys = array_keys($_GET);
    	if ($keys[0] == $id)
    	{
    		$element = array();
    		foreach ($keys as &$key)
    		{
    			if ($_GET[$key] == "") $_GET[$key] = "-1"; //A null values isn't allowed
    			$element[$key] = $_GET[$key];
    		}
    
    		if (is_array($data))
    		{
    			$found = 0;
    			foreach ($data as &$entry)
    			{
    				if ($entry[$id] == $element[$id])		//Replace entry
    				{
    					$entry=$element;
    					$found = 1;
    					break;
    				}
    			}
    			if ($found == 0)	array_push($data,$element);	//Add entry
    		}
    		else
    		{
    			$data = array($element);			//Fist entry
    		}
    		
    		writeData();
    	}
    }
    
    function writeData()
    {
    	global $data, $dataFile;
    	$handle = fopen($dataFile,"w");
    	while(!flock($handle,LOCK_EX))
    	{
    		sleep(1);
    	}
    	$data_string=serialize($data);											// Serialize
    	fwrite($handle,$data_string, strlen($data_string));	// Write
    	flock($handle,LOCK_UN);													// Unlock
    	fclose($handle);																	// Close
    }
    
    function printData()
    {
    	global $data, $id;
    	if (is_array($data))
    	{
    		foreach ($data as &$entry)
    		{
    			$keys = array_keys($entry);
    			if (is_array($keys))
    			{
    				echo $entry[$keys[0]]."=";
    				foreach ($keys as &$key)
    				{
    					if ($key != $keys[0])
    					{
    						echo $key."\=".$entry[$key]."\;";
    					}
    				}
    				echo ";";
    			}
    		}
    	}
    }
    
    ?>
    
    

    Monday, August 27, 2012 5:01 PM
    Moderator
  • OK I figured it out. The data string was to long to be read in that short of a time. so I just reset the data.txt to nothing and it works.

    One thing that is impossible is impossible no matter if it is proven so first.

    Monday, August 27, 2012 5:08 PM
    Answerer
  • How do you use this one?

    One thing that is impossible is impossible no matter if it is proven so first.

    Monday, August 27, 2012 5:10 PM
    Answerer
  • With the modified script, we can run the programs (Player names reversed) and this works pretty well.

    Local = "Player1"
    remote = "Player2"
    GraphicsWindow.KeyDown = OnKeyDown
    
    While ("True")
      url="http://localhost/server/server.php?program="  'Gets data
      data = Network.GetWebPageContents(url)
      TextWindow.Clear()
      TextWindow.WriteLine(data[Local]["x"])
      TextWindow.WriteLine(data[Local]["y"])
      TextWindow.WriteLine(data[Local]["Z"])
      TextWindow.WriteLine(data[remote]["x"])
      TextWindow.WriteLine(data[remote]["y"])
      TextWindow.WriteLine(data[remote]["Z"])
      Program.Delay(100)
    EndWhile
    
    Sub OnKeyDown
      Key = GraphicsWindow.LastKey
      X = GraphicsWindow.MouseX
      Y = GraphicsWindow.MouseY
      url="http://localhost/server/server.php?program="+Local+"&x="+Key+"&y="+ Y + "&Z=" + X  'Sends data
      Network.GetWebPageContents(url)
    EndSub
    

    Good enough to start moving balls in the GraphicsWindow and then maybe firing things.  Perhaps also use x for x, y for y and key for key etc

    Monday, August 27, 2012 5:23 PM
    Moderator
  • Sweet! I'll try that! Thanks!

    One thing that is impossible is impossible no matter if it is proven so first.

    Monday, August 27, 2012 6:12 PM
    Answerer
  • Or this, updating x and y continuously:

    Local = "Player1"
    remote = "Player2"
    GraphicsWindow.KeyDown = OnKeyDown
    GraphicsWindow.KeyUp = OnKeyUp
    
    While ("True")
      x = GraphicsWindow.MouseX
      y = GraphicsWindow.MouseY
      url="http://localhost/server/server.php?program="+Local+"&x="+x+"&y="+y+"&keyDown="+keyDown+"&keyUp="+keyUp  'Sends and gets data
      data = Network.GetWebPageContents(url)
      TextWindow.Clear()
      TextWindow.WriteLine(data[Local]["x"])
      TextWindow.WriteLine(data[Local]["y"])
      TextWindow.WriteLine(data[Local]["keyDown"])
      TextWindow.WriteLine(data[Local]["keyUp"])
      TextWindow.WriteLine(data[remote]["x"])
      TextWindow.WriteLine(data[remote]["y"])
      TextWindow.WriteLine(data[remote]["keyDown"])
      TextWindow.WriteLine(data[remote]["keyUp"])
      Program.Delay(100)
    EndWhile
    
    Sub OnKeyDown
      KeyDown = GraphicsWindow.LastKey
    EndSub
    
    Sub OnKeyUp
      KeyUp = GraphicsWindow.LastKey
    EndSub
    
    There are still edge cases the php fails on so more testing needed.

    Monday, August 27, 2012 6:20 PM
    Moderator
  • You will find another problem - synchronicity - time delays in the commands for the different plays receiving and
     acting on commands.

    Example:

    Modified server.php here and import HGR615.  Make a copy reversing.

    Local = 1
    Remote = 2

    to

    Local = 2
    Remote = 1

    Compile both and run both from command line and use Up and Down arrow keys to test.

    EDIT

    A possible solution, PRD185

    Monday, August 27, 2012 8:29 PM
    Moderator