autre projet en commun , à définir ensemble

Programmation avancée de jeux en PureBasic
Oliv
Messages : 2117
Inscription : mer. 21/janv./2004 18:39

Message par Oliv »

Sinon , un simple jeu de bataille navale pour se faire la main ?
C'est vrai que ce serait peut-être le mieux non ?
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

oui , j'étais en train de regarder pour débuter avec une bataille navale

on compliquera après quand on se sera fait la main :).

j'ai installé la 3.89 beta2 sur mes deux pcs , et j'ai voulu tester l'exemple serveur , client que l'on trouve dans l'aide ,mais pas de pot , il faut changer la gestion d'allocatememory() , bon c'est pas compliqué, mais je voulais juste faire un test rapide , en copiant collant du code sans l'analyser pour l'adapter :?

je vais peut-être repasser en 3.81 pour faire mes essais.

si j'ai le temps , je me plongerai dedans ce week-end .
Oliv
Messages : 2117
Inscription : mer. 21/janv./2004 18:39

Message par Oliv »

c'est quand même pas très dur de changer : *buffer = allocateMemory() on vire le numero, freememory(*buffer) :wink:
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

si c'est très dur je t'assure , surtout quand on a décidé de ne pas toucher au code :)


Je n'ai pas trop la tête à ça en ce moment , je regarderai plus tard :lol:
Oliv
Messages : 2117
Inscription : mer. 21/janv./2004 18:39

Message par Oliv »

ok
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

bon je me suis remis à coder un peu dimanche , et j'ai commencé par la gestion du réseau .

C'est le même programme pour le serveur , et pour le client

celui qui met son pc en serveur démarre le prog en premier , les IP de son PC s'affiche , il indique le bon IP à son petit camarade qui se connecte en client ( en répondant "non" à la première question ).

Ensuite chacun peut envoyer un message à l'autre par l'intermédiaire du menu déroulant.

Avant d'aller plus loin ( commencer la prog du jeu ) j'aimerais améliorer la partie réseau .

Alors ce qui serait bien , c'est que le client puisse détecter le serveur sans saisir l'IP . Comment faire ça ?
Et ce qui serait encore mieux , c'est de détecter si un ami est connecté , à la façon d'ICQ ou MSN.

Ensuite ,je n'utilise qu'un port ,mais si ce port est occupé ,on sort du prog , il faudrait peut-être en tester une série avant de déclarer que c'est impossible de créer une connexion ??

Quelle est la bonne pratique dans ce domaine ??
scruter une centaine de port ? si aucun n'est libre alors c'est qu'il y a vraiment un problème ?

Voila toutes les idées sont les bienvenues pour faire évoluer ce code , et la gestion du réseau :)

ici ça parle de trucs que je ne comprends pas ,mais qui semble correspondre à ce que je voudrais faire ?

http://purebasic.myforums.net/viewtopic ... ght=socket

A suivre...

Code : Tout sélectionner

;Bataille navale en réseau 
;03/05/04
;3.90
;

;{-Les constantes
;/les fenêtres
Enumeration
  #FenetrePrincipale
  #FenetreEnvoiMessage
EndEnumeration

;/les images 
Enumeration
  #ImageJeu
  #ImageDansEau
  #ImageTouche
  #ImageCoule
  #ImageBateau
EndEnumeration
  
;/Les gadgets
Enumeration
  #GDGT_Image
  #GDGT_BoutonOk
  #GDGT_BoutonEnvoi
  #GDGT_StringEnvoi
  #GDGT_StringReception
EndEnumeration  

;/Le menu
Enumeration
  #MenuNouvellePartie
  #MenuQuitter
  #MenuEnvoyerMessage
EndEnumeration
  
;/Divers
#NbCaseX=12
#NbCaseY=12
#LargeurCase=32
#HauteurCase=32
#Yes=6
#No=7
#Cancel=2

#ModeClient=1
#ModeServeur=2

;}
;{-Les variables
Global Gris,Blanc,Rouge,Vert,Bleu
Global ServeurID,ServeurDistantID,ClientID,ModeReseau

Global rc.s 
Gris=RGB(175,175,175)
Blanc=RGB(255,255,255)
Rouge=RGB(255,0,0) 
Vert=RGB(0,255,0)
Bleu=RGB(0,0,255) 
rc=Chr(13) + Chr(10)
Dim MapJoueur(#NbCaseX,#NbCaseY)
Dim MapControle(#NbCaseX,#NbCaseY)
;}
;-Mémoire
*Buffer=AllocateMemory(2000)

;{-Initialisation
;/Réseau
If InitNetwork() = 0 
  MessageRequester("Erreur","Impossible d'initialiser les fonctions réseaux",#MB_ICONERROR) 
  End 
EndIf 
;/Creation du serveur 
Reponse=MessageRequester("Connexion...","créer le serveur sur ce PC ?", #PB_MessageRequester_YesNoCancel)
If Reponse=#Yes         
  ServeurID = CreateNetworkServer(6250) 
  If ServeurID = 0 
    MessageRequester("Erreur","Impossible de créer le serveur",#MB_ICONERROR) 
    End 
  EndIf 
  ;Cherche les IP dispos sur le serveur
  ExamineIPAddresses()
  ip=NextIPAddress()
  While ip
    Ipadresse$=Ipadresse$+IPString(ip)+rc
    ip=NextIPAddress()
  Wend
  MessageRequester("Serveur ok","Liste des IP disponibles sur le serveur"+rc+rc+Ipadresse$,0)  
  ModeReseau=#ModeServeur
ElseIf Reponse=#No    
  ; Connection au serveur 
  Ipserveur.s=InputRequester("Connexion...","Indiquez l'IP du serveur sous la forme xxx.xxx.xxx.xxx ","") 
  ServeurDistantID=OpenNetworkConnection(Ipserveur,6250) 
  If ServeurDistantID=0 
    MessageRequester("Erreur","Impossible de se connecter au serveur.",#MB_ICONERROR) 
    End
  EndIf 
  ModeReseau=#ModeClient
Else                
  End
EndIf 

;/Fenetre et gadgets
FenetreFlag=#PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget
If OpenWindow(#FenetrePrincipale, 0, 0, 500, 450, FenetreFlag, "Bataille navale")=0 Or CreateGadgetList(WindowID(#FenetrePrincipale))=0
  MessageRequester("Pas de pot","Quand ça ne veut pas ça ne veut pas",#PB_MessageRequester_Ok)
  End
EndIf  

;/ un petit menu
If CreateMenu(0,WindowID(#FenetrePrincipale))
  MenuTitle("Partie")
  MenuItem(#MenuNouvellePartie,"Nouvelle Partie")
  MenuItem(#MenuQuitter,"Quitter")
  MenuTitle("Réseau")
  MenuItem(#MenuEnvoyerMessage,"Envoyer un message")
EndIf   

;/une barre 
HandleStatBar.l = CreateStatusBar(0,WindowID(#FenetrePrincipale)) 
If HandleStatBar 
  AddStatusBarField(WindowWidth())
  SendMessage_(HandleStatBar,#SB_GETRECT,0,@StatBarValue.RECT) 
  StatBarHeight.l= StatBarValue\bottom - StatBarValue\top 
EndIf

;/fond du jeu
CreateImage(#ImageJeu,#NbCaseX*#LargeurCase,#NbCaseY*#HauteurCase)
StartDrawing(ImageOutput())
  Box(0,0,ImageWidth() ,ImageHeight(),Gris)
  For x=0 To #NbCaseX-1
    For y=0 To #NbCaseY-1
      DrawingMode(4)
      Box(x*#LargeurCase,y*#HauteurCase,#LargeurCase,#HauteurCase,Blanc)
    Next y
  Next x  
  StopDrawing()  
  DebutX=(WindowWidth()-ImageWidth())/2
  DebutY=(WindowHeight()-ImageHeight()-MenuHeight()-StatBarHeight)/2
ImageGadget(#GDGT_Image,DebutX,DebutY,ImageWidth(),ImageHeight(),ImageID())  
;}
;-Les procedures
Procedure GetMouseX(gadget) 
  GetCursorPos_(mouse.POINT) 
  MapWindowPoints_(0,GadgetID(gadget),mouse,1) 
  ProcedureReturn mouse\x 
EndProcedure 

Procedure GetMouseY(gadget) 
  GetCursorPos_(mouse.POINT) 
  MapWindowPoints_(0,GadgetID(gadget),mouse,1) 
  ProcedureReturn mouse\y 
EndProcedure 

;-Boucle Principale
Repeat
  ;affiche la position de la souris
  StatusBarText(0,0,Str(GetMouseX(#ImageJeu))+" / " + Str(GetMouseY(#ImageJeu))) 
  Select WindowEvent() 
    
    Case #PB_Event_CloseWindow : Quit=1 
    
    Case #PB_Event_Menu 
      
      Select EventMenuID()
        ;/Partie
        Case #MenuQuitter : Quit=1  
        Case #MenuEnvoyerMessage 
          Texte$=""
          If ModeReseau=#ModeServeur
            If ClientID > 0 
              Texte$=InputRequester("Message","Texte à envoyer ","")
              SendNetworkString(ClientID,Texte$) 
            Else 
              MessageRequester("Erreur","il n'y a personne qui joue avec toi !") 
            EndIf 
          Else
            Texte$=InputRequester("Message","Texte à envoyer ","")
            SendNetworkString(ServeurDistantID,Texte$) 
          EndIf  
      EndSelect

  EndSelect 
  
  ;/Test si le prog est lancé en tant que serveur
  If ModeReseau=#ModeServeur
    ;/Ici c'est le serveur 
    ServeurEvent = NetworkServerEvent() 
    If ServeurEvent 
      Select ServeurEvent
        ;/Connexion d'un client 
        Case 1  
          ClientID = NetworkClientID() 
          MessageRequester("Client connecté","on va pouvoir commencer !",0) 
          SendNetworkString(ClientID,"connexion réussie, on va pouvoir commencer !") 
          
        ;/Réception des datas
        Case 2 
          PokeL(*Buffer,500)
          ReceiveNetworkData(NetworkClientID(),*Buffer,2000)
          MessageRequester("Message reçu",PeekS(*Buffer),0)
      EndSelect  
    EndIf  
  
  ;/Ici c'est un client 
  Else
    ClientEvent = NetworkClientEvent(ServeurDistantID) 
    If ClientEvent 
      Select ClientEvent 
        ;/Réception des datas
        Case 2 
          PokeL(*Buffer,500)
          ReceiveNetworkData(ServeurDistantID,*Buffer,2000)
          MessageRequester("Message reçu",PeekS(*Buffer),0)
      EndSelect 
    EndIf
  EndIf  
Until Quit = 1
CloseNetworkServer()  ; est-ce utile avec End ? peut-être que End s'en charge ??
End  
Oliv
Messages : 2117
Inscription : mer. 21/janv./2004 18:39

Message par Oliv »

Je n'ai pas eu trop le temps de regarder mais tout d'abord:
Alors ce qui serait bien , c'est que le client puisse détecter le serveur sans saisir l'IP . Comment faire ça ?
Et ce qui serait encore mieux , c'est de détecter si un ami est connecté , à la façon d'ICQ ou MSN.
Il faudrait que quelqu'un utilise par exemple son FTP et le serveur se connecte dessus et donne son IP : pas pratique si plusieures parties sont lancées. Pour ICQ ou MSN, il faudrait que quelqu'un héberge 24H/24 le serveur et là c'est pas trouvé...
;/Réception des datas
Case 2
PokeL(*Buffer,500)
ReceiveNetworkData(NetworkClientID(),*Buffer,2000)
MessageRequester("Message reçu",PeekS(*Buffer),0)
A quoi sert le PokeL(*Buffer,500) ? Pourquoi mettre le nombre 500 dans le buffer pour le supprimer après ? De plus, il faut faire
;/Réception des datas
Case 2
FreeMemory(*Buffer)
*Buffer = AllocateMemory(2000)
ReceiveNetworkData(NetworkClientID(),*Buffer,2000)
MessageRequester("Message reçu",PeekS(*Buffer),0)
car sinon si on envoi "Et toi ?" et ensuite "Bien" on aura le message "Bienoi ?" car l'ancien contenu du buffer n'aura pas été effacé
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

Oliv a écrit :Il faudrait que quelqu'un utilise par exemple son FTP et le serveur se connecte dessus et donne son IP : pas pratique si plusieures parties sont lancées. Pour ICQ ou MSN, il faudrait que quelqu'un héberge 24H/24 le serveur et là c'est pas trouvé...
Ok dans ce cas ,je crois que je vais m'en passer :)
Merci pour l'info , je vais donc pour l'instant me contenter d'améliorer la présentation de ce qui est déjà fait ( pour sélectionner le mode serveur ou client au démarrage ).
A quoi sert le PokeL(*Buffer,500) ? Pourquoi mettre le nombre 500 dans le buffer pour le supprimer après ?
C'est une modif de dernière minute que je n'ai pas pris le temps de tester , et effectivement ça n'a pas lieu d'être , du moins sous cette forme :).
;/Réception des datas
Case 2
FreeMemory(*Buffer)
*Buffer = AllocateMemory(2000)
ReceiveNetworkData(NetworkClientID(),*Buffer,2000)
MessageRequester("Message reçu",PeekS(*Buffer),0)

car sinon si on envoi "Et toi ?" et ensuite "Bien" on aura le message "Bienoi ?" car l'ancien contenu du buffer n'aura pas été effacé
oui j'ai remarqué ça , mais seulement pour le premier message ,ensuite , les messages s'échangent correctement .Bon j'ai testé ça rapidement dimanche soir , et je voulais éviter de passer par
FreeMemory(*Buffer)
*Buffer = AllocateMemory(2000)
Donc je vais faire encore quelques tests pour confirmer ce que je dis , à savoir que le problème du Buffer qui ne se vide pas n'existe que pour le premier message .C'est étonnant , j'ai sûrement mal testé :)

pourtant j'alternais des messages longs avec des messages courts , et chaque message arrivait correctement , à suivre.

Et merci pour tes remarques .
Avatar de l’utilisateur
cederavic
Messages : 1338
Inscription : lun. 09/févr./2004 23:38
Localisation : Bordeaux

Message par cederavic »

salut :)
il y a le CloseNetworkServer() a la fin qui ne sert a rien quand on est en client lol
Sinon, je te conseil de bient separer la partie reseau et le jeu en lui meme, mettre plutot la partie reseau dans un thread. Et surtout, fait en sorte que le serveur ne recoit des truc du client seulement lorsqu'il a fini de traité ce qu'il lui avais envoier avant sinon il vas tres vite surcharger, bouffer pas mal de memoire, et ce melanger les pinceaux dans la reception ;) (encor quoique pour un jeu a 2 seulement, je pense pa que se sera tres souvent... enfin on sais jamais.. suffit que le serveur ram un bon coup pendant 10 secondes, 10 secondes pendant lesquelles le client vas le tartiné de message...)

voilou :)
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

cederavic a écrit :salut :)
il y a le CloseNetworkServer() a la fin qui ne sert a rien quand on est en client lol

oui , oui , c'est un premier bout de code qui demande encore à être travaillé , je vais en tenir compte :)

Je me demandais si End ne gérait pas ça tout seul ? que fait exactement End ??
Sinon, je te conseil de bient separer la partie reseau et le jeu en lui meme, mettre plutot la partie reseau dans un thread. Et surtout, fait en sorte que le serveur ne recoit des truc du client seulement lorsqu'il a fini de traité ce qu'il lui avais envoier avant sinon il vas tres vite surcharger, bouffer pas mal de memoire, et ce melanger les pinceaux dans la reception ;)
oui tu as raison , d'ailleurs je devrais tester le réception de la réception si c'est égal à la longueur indiquée , c'est qu'il y en a encore ,et je devrais boucler pour tout récupérer , c'est à faire pour la prochaine version :)
suffit que le serveur ram un bon coup pendant 10 secondes, 10 secondes pendant lesquelles le client vas le tartiné de message...)
voilou :)
c'est ce point là qui m'ennuie , dans un jeu comme une bataille navale ce n'est pas gênant si ça rame un peu par moment , mais ensuite je pensais faire un jeu qui demande des rafraichissement plus fréquent ( une bataille temps réelle (style FPS ) entre deux à 4 joueurs ) , et je me demandais comment synchroniser la partie , bon , ça viendra après , chaque chose en son temps , d'abord un truc simple , on compliquera peut-être après .

Merci pour tes mises en garde :)
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

mettre plutot la partie reseau dans un thread
j'ai oublié de te dire que c'était une excellente suggestion !

Comme je n'ai encore jamais utilisé les threads ,c'est l'occasion d'apprendre sur ce projet :)

et c'est aussi l'occasion de commencer à utiliser les gadgets , je vais en coller un peu , histoire de me faire la main , fini la 3D , place aux gadgets :lol: ( il serait temps que je m'y mette d'ailleurs )
Avatar de l’utilisateur
Flype
Messages : 2431
Inscription : jeu. 29/janv./2004 0:26
Localisation : Nantes

Message par Flype »

comme çà tu pourras faire un editeur plein de gadgets pour tes jeux 3d :lol:
Image
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

oui j'avais commencé à en faire un , et puis j'étais bloqué avec les gadgets , mais je vais le ressortir , j'ai commencé à le reprendre en utilisant le MDIGadget ,c'est exactement ce dont j'avais besoin :)

maintenant mon problème c'est la gestion des tiles dans une fenêtre ( j'utilisais une ListIconGadget pour la simplicitée)
Je voudrais avoir le même comportement d'affichage , mais avec des images d'une taille supérieure à 32x32 ! .
là je pense que j'aurai à le gérer entièrement , puisqu'apparemment la listeicone est limitée pour la dimension des images ( pour les images de taille supérieure à 32x32 , je doublais les images , en faisant un resize pour la liste icone, et quand je sélectionnais une icone , j'affichais l'image dans sa dimension réelle , solution pas très satisfaisante .

Je n'ai pas encore cherché comment faire autrement, c'est une autre histoire ,j'en reparlerai plus tard .
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

comtois a écrit : maintenant mon problème c'est la gestion des tiles dans une fenêtre ( j'utilisais une ListIconGadget pour la simplicitée)
Je voudrais avoir le même comportement d'affichage , mais avec des images d'une taille supérieure à 32x32 ! .
là je pense que j'aurai à le gérer entièrement , puisqu'apparemment la listeicone est limitée pour la dimension des images ( pour les images de taille supérieure à 32x32 , je doublais les images , en faisant un resize pour la liste icone, et quand je sélectionnais une icone , j'affichais l'image dans sa dimension réelle , solution pas très satisfaisante .

Je n'ai pas encore cherché comment faire autrement, c'est une autre histoire ,j'en reparlerai plus tard .

L'affichage des images dans la listIcon (pour les éléments) se fait en utilisant une imageList dont la taille des icônes est définie une fois pour toute pour toutes les images, en général la taille est définie en utilisant l'API GetSystemMetrics avec les paramètres SM_CXICON et SM_CYICON.

On peut définir une autre taille même non symétrique pour les icônes.

L'API ImageList_SetIconSize permet de définir une autre taille pour les images de la liste mais son inconvénient est de supprimer toutes les images de la liste.

PB va créer l'ImageLIst lorsque tu assigne la première image à un élément. Essaye ceci : lorsque tu assigne l'iamge au premier élément, utilise l'API ImageList_SetIconSize pour redéfinir la taille et réassigne la même image à ce premier élément. Maintenant, il y aura peut-être un problème car la première image de la liste est une image transparente. Elle aura peut-être disparue.

Sinon on peut avant d'assigner la première image, créer une listImage avec l'API ImageList_Create en fixant la taille voulue pour les images.


J'ai posté quelques exemples sur le forum anglais y compris pour les afficher des images pour les éléments des colonnes autre que la 1ere.

http://purebasic.myforums.net/viewtopic ... listcreate

http://purebasic.myforums.net/viewtopic ... c&start=15


Ces exemples ne sont pas parfaits mais donne une idée.
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

Merci Denis

Je vais regarder ça dans le détail , ça a l'air de correspondre exactement à mon besoin :)
Répondre