JeuWeb - Crée ton jeu par navigateur
Optilisation map - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : Optilisation map (/showthread.php?tid=2206)



Optilisation map - phenix - 29-12-2007

Bonjour à tous,

Voila, je me retrouve devant un problème épineux.

Mon tout beau système de map est trop lourd pour le serveur, il cause de nombreux plantage.

Je cherche a l'optimiser au maximum.

Avant de balancer bêtement du code, je explique comment il fonctionne.

Une map, cher moi sa ressemble a sa:

herbe*rocher*bazar1*bazar2*rocher*herbe*fleur*etc...

j'explode le tout et j'appelle une fonction qui s'occupe de me crée un <td> en fonction.

Je dispose également de 2 fichier index qui liste les type de case. (les décor, les case sur les quelles on peut marcher et les batiments)
afin dans faire des tableaux pour comparer.

cette fonction s'occupe aussi de placer les joueurs et les monstres sur ma map.

Une map fait 408 cases, cela veux dire que la fonction est appelé 408 fois. Visiblement, c'est trop pour elle.

Voici les codes:
Code PHP :
<?php 
//on lit la map
$r = read_file($path);
$r = explode('*',$r);

//on crée le tableau des joueurs
$sql = mysql_query('SELECT position FROM users WHERE lieu=\''.$lieu.'\' and quartier=\''.$quartier.'\' and statut=\'1\'') or die(mysql_error());
$tab_pos = array();
while (
$a = mysql_fetch_assoc($sql))
{
array_push($tab_pos,$a['position']); }

//on y ajoute le tableau des monstres
$sql = mysql_query('SELECT position FROM monstre WHERE lieu=\''.$lieu.'\' and quartier=\''.$quartier.'\'') or die(mysql_error());
while (
$a = mysql_fetch_assoc($sql))
{
array_push($tab_pos,$a['position']); }

//Tableau des objets
$tab_objet = array();
$sql = mysql_query('SELECT position FROM objet_sol WHERE lieu=\''.$lieu.'\' and quartier=\''.$quartier.'\'') or die(mysql_error());
while (
$a = mysql_fetch_assoc($sql))
{
array_push($tab_objet,$a['position']); }

//on lit les index
$open = read_file('index_bat');
$tab_bat = explode('*',$open);
$open = read_file('index_fond');
$tab_case_dep = explode('*',$open);
$open = read_file('index_decor');
$tab_decor = explode('*',$open);
?>
<div align="center">
<table class="main_table">
<?php
//include du menu
include('menu.php');
echo
'
<tr>
<td class="table_center_map">'
;
echo
'<a href="#" onmouseover="overlib(\'<object data=fiche.php class=fiche_perso_vue type=text/html>\');" onmouseout="rd();">Fiche du personnage</a>
<table class="table_map" cellspacing="0" cellpadding="0">'
;
$x=0;
while (
$x<$hauteur)
{
echo
'<tr>';
$y = 0;
while (
$y<$largeur)
{
$modul = $x*$largeur+$y;
echo
recup_td($r[$modul],$modul,$tab_pos,$tab_objet,$position,$lieu,$quartier,$largeur,$guilde,$groupe,$tab_bat,$tab_case_dep,$tab_decor);
$y++;
}
echo
'</tr>';
$x++;
}
echo
'</table>';

Ceci affiche la map.

Voici la fonction qui crée le td:

Code PHP :
<?php 
//interpréteur.
function recup_td($s,$case,$tab_poss,$tab_objet,$pos_joueur,$lieu,$quartier,$largeur,$guilde,$groupe,$tab_bat,$tab_case_dep,$tab_decor)
{
if (
in_array($case,$tab_poss))
{
//selection de l'éventuel joueur sur la case
$sql = mysql_query('SELECT id,pseudo, orientation, groupe, guilde FROM users WHERE position=\''.$case.'\' and quartier=\''.$quartier.'\' and lieu=\''.$lieu.'\' and statut=\'1\'') or die(mysql_error());
$a = mysql_fetch_assoc($sql);
//s'il n'y a pas de joueur, il y a peut être un monstre
if (empty($a['pseudo']))
{
$sql = mysql_query('SELECT id,nom FROM monstre WHERE position=\''.$case.'\' and quartier=\''.$quartier.'\' and lieu=\''.$lieu.'\'') or die(mysql_error());
$i = mysql_fetch_assoc($sql);
$id_monstre = $i['id'];}
}

//contruction des actions possible si le joueur est proche de la case
$action = '';
$titre = '';
if (
is_proche($pos_joueur, $case, $largeur,1))
{
//Case sur lesquel il est possible de ce déplacer
if (in_array($s,$tab_case_dep) and $pos_joueur !== $case)
{
$action = '<ul><li><a href=vue.php?dep='.$case.'>Se déplacer (1 PM)</a></li></ul>';
$titre = 'Case de déplacement';}
//BATIMENT s'il est proche d'un batiment
if (in_array($s,$tab_bat))
{
$action = '<ul><li><a href=batiment/'.clear_bat($s).'.php>Entrer dans le batiment</a></li></ul>'; }

//Changeur de quartier s'il est proche du point de changement de quartier
if ($s === 'quartier_herbe' or $s === 'quartier_pave')
{
$action = 'Selectionnez un quartier:<ul>';
$sql = mysql_query('SELECT quartier FROM liste_quartier WHERE lieu=\''.$lieu.'\'') or die(mysql_error());
while (
$t = mysql_fetch_assoc($sql))
{
$action .= '<li><a href=vue.php?quartier='.str_replace(' ','%20',$t['quartier']).'>'.$t['quartier'].'</a> (2 PA/6 PM)</li>';}
$action .= '</ul>';
}
//Accès a la zone résidentiel s'il est proche du point d'accès au résidence
if ($s === 'residence_herbe' or $s === 'residence_pave')
{
$action = '<a href=vueresidence.php>Accès à la zone résidentiel.</a>';

}
if (
$s === 'coffre')
{
$action = '<ul><li><a href=residence.php?res='.$quartier.'>Gestion du batiment</a></li></ul>';
}
}

//Action sur un joueur
if (!empty($a['pseudo']) and $pos_joueur !== $case and $s !== 'quartier_herbe' and $s !== 'quartier_pave')
{
$action = '<ul><li><a onclick=popup_profil('.$a['id'].');>Profil</a></li><li><a href=attaque.php?cible='.$a['pseudo'].'>Attaquer</a></li><li><a href=sort.php?cible='.$a['pseudo'].'&type=joueur>Sort/compétence</a></li></ul>';
$titre = create_profil($a['pseudo']);
}

//Action sur un monstre
if (!empty($i['nom']) and $pos_joueur !== $case and $s !== 'quartier_herbe' and $s !== 'quartier_pave')
{
$action = '<ul><li><a href=attaquemonstre.php?cible='.$i['id'].'>Attaquer</a></li><li><a href=sort.php?cible='.$i['id'].'&type=monstre>Sort/compétence</a></li></ul>';
$titre = create_profil_monstre($i['id']);
}

//Action sur soi !
if ($pos_joueur === $case)
{
$action = '<ul><li><a onclick=popup_profil('.$a['id'].');>Profil</a></li><li><a href=sort.php?cible='.$a['pseudo'].'&type=joueur>Sort/compétence sur soi</a></li></ul>';
$titre = 'Votre personnage.';

if (
in_array($case,$tab_objet))
{
$sql = mysql_query('SELECT id,objet FROM objet_sol WHERE position = \''.$case.'\' and lieu=\''.$lieu.'\' and quartier=\''.$quartier.'\'') or die(mysql_error());
$action .= '<br /><br /><hr><br />Objet sur la case:<br />';
while (
$q = mysql_fetch_assoc($sql))
{
$action .= '<br />'.$q['objet'].' <a href=vue.php?objet='.$q['id'].'> <img src=image_carte/ramasser.gif /> (1 PA)</a>';}
}
//si le joueur est sur un changeur de quartier.
if ($s === 'quartier_pave' or $s === 'quartier_herbe')
{
$action .= '<hr><br />Selectionnez un quartier:<ul>';
$sql = mysql_query('SELECT quartier FROM liste_quartier WHERE lieu=\''.$lieu.'\'') or die(mysql_error());
while (
$t = mysql_fetch_assoc($sql))
{
$action .= '<li><a href=vue.php?quartier='.str_replace(' ','%20',$t['quartier']).'>'.$t['quartier'].'</a> (2 PA/6 PM)</li>';}
$action .= '</ul>';
}
}
//on regarde s'il y a des objets sur la case
if (in_array($case,$tab_objet))
{
$titre .= '<br /><hr><br />Objet sur la case:<br />';
$sql = mysql_query('SELECT objet FROM objet_sol WHERE position = \''.$case.'\' and lieu=\''.$lieu.'\' and quartier=\''.$quartier.'\'') or die(mysql_error());
while (
$q = mysql_fetch_assoc($sql))
{
$titre .= '<br />'.$q['objet'];}
if (empty(
$a['pseudo']) and empty($i['nom']))
{
$bat = '<img src="image_carte/objet_sol.gif" />'; }
}

//BATIMENT s'il y a un batiment on crée l'image
if (in_array($s,$tab_bat))
{
$bat = '<img src="image_carte/bat/'.$s.'.gif" />'; $titre = no_num($s);
}

//Si c'est un changeur de quartier, on crée l'image et on crée les quartier disponible
if (($s === 'quartier_pave' or $s === 'quartier_herbe') and $case !== $pos_joueur)
{
$bat = '<img src="image_carte/quartier.gif" />';
$titre = 'Changer de quartier';

$sql = mysql_query('SELECT pseudo FROM users WHERE lieu=\''.$lieu.'\' AND quartier=\''.$quartier.'\' AND position=\''.$case.'\'') or die(mysql_error());
$titre .= '<br /><br /><u>Joueur sur la case</u>:';
while (
$a = mysql_fetch_assoc($sql))
{
$titre .= '<br />'.$a['pseudo'];
}

}
//si c'est un point de résurection ob le crée et on affiche les autre joueur qui sont dessus
elseif (($s === 'resu_pave' or $s === 'resu_herbe') and $case !== $pos_joueur)
{
$bat = '<img src="image_carte/resu.gif" />';
$titre = 'Portail de résurection';

$sql = mysql_query('SELECT pseudo FROM users WHERE lieu=\''.$lieu.'\' AND quartier=\''.$quartier.'\' AND position=\''.$case.'\'') or die(mysql_error());
$titre .= '<br /><br /><u>Joueur sur la case</u>:';
while (
$a = mysql_fetch_assoc($sql))
{
$titre .= '<br />'.$a['pseudo'];
}
}
//Si c'est l'accès a la zone résidentiel, on la crée
elseif ($s === 'residence_herbe' or $s === 'residence_pave')
{
$bat = '<img src="image_carte/residence.gif" />';
$titre = 'Accès à la zone résidentiel.';
}
if (
$s === 'coffre')
{
$titre = 'Gestion du batiment'; }
//initialistion de la variable qui contiendra le TD final
$td = '<td ';

//On selectionne le type de fond de la case
//HERBE, tout les case qui on un font herbeux, mais sur lequel on ne peu pas marcher
$tab_herbe = array( 'herbe',
'roche1','roche2','roche3','roche4',
'quartier_herbe',
'arbre_feuille','arbre_pleureur','arbre_feuillu1','conifere1','conifere2','arbre_mort1','arbre_mort2','arbre_mort3',
'statue1','statue2','statue3','statue4',
'pilier1','pilier2',
'mine1','mine2','mine3','mine4',
'tunnel',
'SN1','SN2','SN3','SN4','SN5','SN6','SN7','SN8','SN9',
'ecurie1','ecurie2','ecurie3','ecurie4',
'tombe1','tombe2','tombe3','tombe4',
'buisson1','buisson2','buisson3',
'piquet1','piquet2',
'montagne1','montagne2','montagne3','montagne4','montagne5','montagne6',
'residence_herbe',
'resu_herbe'
);
//TABLEAU DES PAVES, tout les case qui on un font pavé, mais sur lequel on ne peux pas marcher
$tab_pave = array( 'pave','quartier_pave',
'bazar1','bazar2','bazar3','bazar4',
'fanal1','fanal2','fanal3','fanal4',
'hotel_guilde1','hotel_guilde2','hotel_guilde3','hotel_guilde4',
'HV1','HV2','HV3','HV4','HV5','HV6','HV7','HV8','HV9',
'AE1','AE2','AE3','AE4',
'AN1','AN2','AN3','AN4',
'AA1','AA2','AA3','AA4',
'forge1','forge2','forge3','forge4',
'acaforge1','acaforge2','acaforge3','acaforge4',
'marelle',
'camp_entr1','camp_entr2','camp_entr3','camp_entr4',
'arsenal1','arsenal2','arsenal3','arsenal4',
'bucheron1','bucheron2','bucheron3','bucheron4',
'fort1','fort2','fort3','fort4',
'repaire1','repaire2','repaire3','repaire4',
'hopital1','hopital2','hopital3','hopital4',
'temple1','temple2','temple3','temple4','temple5','temple6','temple7','temple8','temple9',
'fontaine',
'fontaine1','fontaine2',
'residence_pave',
'coffre',
'resu_pave'
);

//Déclaration
if (in_array($s,$tab_herbe))
{
$td .= 'style="background: url(\'image_carte/herbe.gif\');"'; }
if (
in_array($s,$tab_pave))
{
$td .= 'style="background: url(\'image_carte/pave.gif\');"'; }

//font eau pour le batiment du port
if ($s === 'port2' or $s === 'port4')
{
$td .= 'style="background: url(image_carte/eau.gif);"'; }
//font bord de l'eau pour le batiment du port
if ($s === 'port1' or $s === 'port3')
{
$td .= 'style="background: url(image_carte/bord_eau.gif);"'; }

//On afiche la case de déplacement
if (in_array($s,$tab_case_dep))
{
$td .= 'style="background: url(\'image_carte/'.$s.'\');"';
}
//mise des actions, on crée le javascript
$td .= ' onMouseOver="return overlib(\''.$titre.'\', SNAPX, 50, SNAPY, 30, CAPTION, \'Position: Y: '.y($case,$largeur).'/X: '.x($case,$largeur).' | '.$case.'\');" onClick="return overlib(\''.$action.'\', STICKY, CAPTION, \'Action: \');" onMouseOut="return nd();"';

//Ajout de la class
$td .= ' class="map">';

//Selection de l'image au centre
//JOUEUR
//déclaration de la bodure si besoin
//Joueur de la même guilde
if (!empty($a['guilde']) and $a['guilde'] === $guilde)
{
$bordure = 'style="border: 1px solid #00FF00;"';}
//Joueur du même groupe de chasse
if (!empty($a['groupe']) and $a['groupe'] === $groupe)
{
$bordure = 'style="border: 1px solid #4400ff;"';}
//Joueur en lui même :D
if ($pos_joueur === $case)
{
$bordure = 'style="border: 1px solid #FF0000;"';}

//Récupération de l'avatar en fonction de la classe du personnage
switch ($a['orientation']) {
//Guerrier
case 'Guerrier':
$td .= '<img src="image_carte/perso/guerrier.gif" '.$bordure.' />';
//Chevalier
break; case 'Chevalier':
$td .= '<img src="image_carte/perso/chevalier.gif" '.$bordure.' />';
//Paladin
break; case 'Paladin':
$td .= '<img src="image_carte/perso/paladin.gif" '.$bordure.' />';
//Barbare
break; case 'Barbare':
$td .= '<img src="image_carte/perso/barbare.gif" '.$bordure.' />';
//Trompe la mort
break; case 'Trompe la mort':
$td .= '<img src="image_carte/perso/trompelamort.gif" '.$bordure.' />';
//Berserk
break; case 'Berserk':
$td .= '<img src="image_carte/perso/berserk.gif" '.$bordure.' />';
//Assassin
break; case 'Assassin':
$td .= '<img src="image_carte/perso/assassin.gif" '.$bordure.' />';
//Tueur
break; case 'Tueur':
$td .= '<img src="image_carte/perso/tueur.gif" '.$bordure.' />';
//Ombre
break; case 'Ombre':
$td .= '<img src="image_carte/perso/ombre.gif" '.$bordure.' />';
//Rôdeur
break; case 'Rôdeur':
$td .= '<img src="image_carte/perso/rodeur.gif" '.$bordure.' />';
//Pisteur
break; case 'Pisteur':
$td .= '<img src="image_carte/perso/pisteur.gif" '.$bordure.' />';
//Traqueur
break; case 'Traqueur':
$td .= '<img src="image_carte/perso/traqueur.gif" '.$bordure.' />';
//Mage
break; case 'Mage':
$td .= '<img src="image_carte/perso/mage.gif" '.$bordure.' />';
//Nécromant
break; case 'Nécromant':
$td .= '<img src="image_carte/perso/necromant.gif" '.$bordure.' />';
//Elemeantaliste
break; case 'Elémentaliste':
$td .= '<img src="image_carte/perso/elementaliste.gif" '.$bordure.' />';
//Prêtre
break; case 'Prêtre':
$td .= '<img src="image_carte/perso/pretre.gif" '.$bordure.' />';
//Prêtre guerrier
break; case 'Prêtre guerrier':
$td .= '<img src="image_carte/perso/pretreguerrier.gif" '.$bordure.' />';
//Ermite
break; case 'Ermite':
$td .= '<img src="image_carte/perso/ermite.gif" '.$bordure.' />';
}

//Les joueurs qui on réserver un monstre le voie entouré d'un carré bleu
if (!empty($groupe))
{
$sql = mysql_query('SELECT id_monstre FROM groupe WHERE nom=\''.$groupe.'\'') or die(mysql_error());
$zer = mysql_fetch_assoc($sql);
if (
$id_monstre === $zer['id_monstre'])
{
$bordure = 'style="border: 1px solid #4400ff;"';}
}

//MONSTRE, on affiche le monstre
if (!empty($i['nom']) and $s !== 'quartier_pave' and $s !== 'quartier_herbe')
{
$td .= '<img src="image_carte/monstre/'.clear_bat($i['nom']).'.gif" '.$bordure.' />'; }

//DECOR, on affiche l'éventuel d"cor, (rocher, arbre, tombe...)
if (in_array($s,$tab_decor))
{
$td .= '<img src="image_carte/'.$s.'.gif" />';
}
$td .= $bat;

//On referme la TD
$td .= '</td>';

return
$td;
}


Mais voila, il semble que ce soit trop lourd pour le serveur... (ce qui en faite n'a rien d'étonnant...)

Merci d'avance de votre aide.

Phenix


RE: Optilisation map - jo_link_noir - 29-12-2007

salut,

appeler une fonction 408 fois ou plus c'est largement faisable, par contre faire 408 fois une requête sql, ça c'est pas bon, et encore, je parle que des 1er ligne de la fonction...
Vu que là -à ce que j'ai comprit- tu prends tout les joueur et monstre de la carte, fait une requête au début du while qui les prends tous d'un coup, ensuite tu fait en sorte d'envoyer les bonnes valeur à t'as fonction.
Ne faire que 2/3 requêtes serais déjà une bonne optimisation


RE: Optilisation map - phenix - 29-12-2007

Citation :vu que là -à ce que j'ai comprit- tu prends tout les joueur et monstre de la carte, fait une requête au début du while qui les prends tous d'un coup, ensuite tu fait en sorte d'envoyer les bonnes valeur à t'as fonction.
Ne faire que 2/3 requêtes serais déjà une bonne optimisation

C'est presque sa.

Je recherche d'abord les positions des joueur et des monstres.

La fonction de fait de requête SQL que si c'est nécessaire (joueur/monstre sur la map, cases particulières)

C'est tout.


RE: Optilisation map - Asherah - 29-12-2007

Pourquoi s'obstiner a gerer et afficher une map en php?
Enfin,bon apres chacuns son truc, mais d'autres formes de programation sont beaucoup plus adapter a ce genre de réalisation.
Le Flash et action script serait beaucoup plus judicieux, ou meme le javascripts, tu charge ta map de base et ensuite tu positionne tes objets avec les coordonnées x et y;
tu peut meme faire un systeme de tuiles pour delimiter les zones accessibles ou non, un peu a la façon rpg-maker.
L'avantage du flash et quand meme de pouvoir faire du drag and drop assé facilement.
et meme creer un éditeur de map online ^^.


RE: Optilisation map - phenix - 29-12-2007

Citation :Pourquoi s'obstiner a gerer et afficher une map en php?
Enfin,bon apres chacuns son truc, mais d'autres formes de programation sont beaucoup plus adapter a ce genre de réalisation.
Le Flash et action script serait beaucoup plus judicieux, ou meme le javascripts, tu charge ta map de base et ensuite tu positionne tes objets avec les coordonnées x et y;
tu peut meme faire un systeme de tuiles pour delimiter les zones accessibles ou non, un peu a la façon rpg-maker.
L'avantage du flash et quand meme de pouvoir faire du drag and drop assé facilement.
et meme creer un éditeur de map online 34.

Pourquoi en php ? Parce que mes connaissances je JS sont limiter a ouvrir une alert, faire un redirection, et jouer avec les popups.

Le flash, on oublie, c'est une technologie propriétaire.

Action-script, je sais même pas ce que c'est :good:

Merci quand même, c'est vrai que je devrais me mettre au JS...

phenix


RE: Optilisation map - Asherah - 29-12-2007

Les logiciel flash sont propriétaire tel que macromadia flash ou adobe flash ou encore flash mx, il y en a aussi des gratuit (comme GPLFlash mais je ne les connais pas),sinon actionscript c'est le language objet comparable au javascript, d'ailleur actionscript n'est qu'un language javascript "standardisé".
En parlant de ca, je sait que actionscript a été dévloppé pour macromedia et qui lui est donc propriétaire, mais je pense que tout le monde peut l'utiliser...
Je cherche justement un peu plus d'infos la dessus, mais je n'en trouve pas des masses.
Si quelqu'un a cette reponse.


RE: Optilisation map - Sephi-Chan - 29-12-2007

Je ne sais pas si ça répond vraiment à ta question, mais j'ai lu que Adobe avait ouvert le code de sa machine virtuelle ActionScript. J'ignore par contre si ça libère le langage en lui même.


Sephi-Chan


RE: Optilisation map - phenix - 30-12-2007

Citation :Mais faire une requête qui te liste TOUT ce qu'il y a sur la map où le joueur est présent,

Au risque de passer pour un gros nul,comment tu fais ce genre de requête ? :toilette:

Parce que bon, les infos sont dans des tables différentes (une pour les objets, une pour les joueurs, une pour les monstres, une pour les quartiers de chaque ville...)

De même, comment je peux répuré dans cette requête, a la fois les infos du joueur, les noms des objets sur les cases, les info des monstres... ?

Citation :chaque objet sur la map ayant ses coordonnées x,y, tu l'affiches facilement

Pourrais tu expliquer le facilement ? J'ai du mal a voir comment tu peux faire tout sa :heuuu:


Amicalement,

Phenix


RE: Optilisation map - phenix - 30-12-2007

Tout d'abors, merci de l'intéret que tu porte a mon problème.

Si je comprend bien, il faudrais une table en plus qui contiendrais les id de chaque élément sur la map et leur position.

Pour la base de donnée, c'est très simple (enfin je pense).

J'ai 3 table, j'écris pas tout, juste ce qui faut pour la map:

users:
[info du joueur]
lieu
quartier
position

monstre:
[info du monstre]
lieu
quartier
position

objet_sol:
[info objet]
lieu
quartier
position

Si j'ai bien comprit, tu me propose de centraliser le tout sur une seul table ?

Mais je devrais quand même faire des requêtes sur les autres table pour récupéré les infos en fonctionne de l'ID non ???


RE: Optilisation map - phenix - 30-12-2007

Cela ne me semble pas impossible a faire. (h)

Par pur intéret, et dans le but d'augmenté mes connaissances, pourrais tu expliqué ta requête sql ?

Code :
SELECT id_element, id_type,

Jusque la sa va Cool

Code :
CASE id_type WHEN '1' THEN nom_joueur WHEN '2' THEN nom_monstre WHEN '3' THEN nom_objet END AS nom_element,

Je connais pas, ca fait quoi exactement ?:heuuu:
Code :
LEFT JOIN joueur ON (id_type = '1' and id_element = id_joueur)
LEFT JOIN monstre ON (id_type = '2' and id_element = id_monstre)
LEFT JOIN objet ON (id_type = '3' and id_element = id_objet)

Tu fait un jointure, mais j'ai du mal a comprendre ce qui ce trouve dans les ON :respect:

Merci de ton aide,

Phenix