probleem met 'constructor' (javascript oop)

Status
Niet open voor verdere reacties.

That Guy

Meubilair
Lid geworden
28 nov 2006
Berichten
5.010
beste javascripters,

Ik hoop niet dat iemand ontmoedigd raakt deze vraag te beantwoorden door de lengte.

Ik zit met een probleem en ik kan niet achter de oplossing komen. Omdat het nogal veel code is (1000+ regels) is het nutteloos het allemaal te plaatsen, maar ik zal even de belangrijkste dingen erbij zetten.


Ik ben bezig met een javascript 'tile' engine, welke met een 16x16 map van divjes werkt en ik steeds de background aanpas via javascript. het werkt allemaal perfect. Maps laden goed en ik kan de player bewegen.

bewegen doe je met de pijltjes ( <- en -> en v en ^ ). Als je op 1 van de tiles klikt zie je in de debug de locatie x en y en de tile's graphic en 'trigger' (graphic,trigger) en daarna de 'i' locatie. (alle div's hebben een nummer).

Javascript heb ik allemaal omgezet naar wat meer OOP achtige stijl. Eerst had ik alles met losse functies en variabelen, en had ik precies hetzelfde probleem.

Mischien een beetje verwarrend, maar het staat hier online: www.vegras-studios.com/X/tile/ (!!! alleen te zien met FF, IE werkt niet goed....!!!)

Hier even wat code:
PHP:
//js
//korte versie van player.js...
function c_Player(Pname,Ploc,Pfacing){


   this.name = Pname;
   this.loc = Ploc;

   this.facing = Pfacing;

   this.setloc = function(xloc){
      this.loc = xloc;
   }


   this.drawplayer = function(loc){
      var retval = "url( // hier staat een url naar het plaatje van het mannetje // )";
      document.getElementById(loc).style.background = retval;
      this.loc = loc;
   }

// (...)
deze wordt aangeroepen door deze code:
PHP:
//js
var Player = new c_Player('TestGuy',Game.startloc,Game.startfacing);


tot zover werkt het dus. Een mapchange werkt zo:
PHP:
//js
      Game.updatemap(map2);
dit wordt getriggerd. De Game-constructor:
PHP:
//js

function c_Game(Pmap,playerstart,Pstartfacing){

   this.map = Pmap;
   this.startloc = playerstart;
   this.startfacing = Pstartfacing;

   DisplayMap(this.map.mapArray,this.map.bg);

   this.updatemap = function(Pnewmap){
      this.map = Pnewmap;
      DisplayMap(this.map.mapArray,this.map.bg);

   }

}
functie DisplayMap werkt 100% goed.


het eigenlijke probleem:
Als ik naar een nieuwe map ga, wordt dit dus mooi getekent, MAAR de player wordt niet op de nieuwe locatie geplaats, en blijft dus op de plek van de oude map.

Ook dit werkt niet:
PHP:
//js
Player.setloc(32)
en ook
PHP:
//js
Player.drawplayer(32)
werkt niet.



Als je naar de nieuwe map gaat, zie je 2 alerts: de 1e is de oude player's locatie (Player.loc) en de 2e is de Player.loc NA de Player.setloc(32) call.

Bovendien wordt er dus wel een 'player' getekent op 2,2 (i=32) maar deze is niet te 'besturen'.





Alvast heel erg bedankt,

V. :thumb:
 
Laatst bewerkt:
Ik heb het probleem gevonden denk ik.

Het zit hem in de c_Player.walk() en de CallTrigger() functie.

Je berekent eerst de nieuwe positie, vervolgens wordt de trigger geroepen en dan wordt de nieuwe positie pas geset. CallTrigger roept player.newMap() die de positie goed zet, maar vervolgens wordt de "nieuwe" positie van het lopen weer neer gezet.

Twee kleine aanpassingen verhelpen het, maar nou blijft de tile die je transporteert groen. De tile waar je dus zou zijn als je niet getransporteert was.

Code:
/*////////////////////////////////
// c_Player               //
///////////////////////////////*/
   this.newmap = function(testj){
[COLOR="Red"]     this.setloc(Game.map.playerstart);
     this.facing = Game.map.playerface;
     this.drawplayer(this.loc);[/COLOR]
   }


   this.walk = function(gm_side){

      OutputGame(Player.loc);
      var oldLoc = this.loc;
      var newLoc;
      var x = 14;
      var gm_new;
      var temp;
      var l0;
      var l1;

      switch(gm_side.name)
      {
      case "up":
         newLoc = oldLoc - x -1;
         break;
      case "down":
         newLoc = oldLoc + x +1;
         break;
      case "right":
         newLoc = oldLoc + 1;
         break;
      case "left":
         newLoc = oldLoc - 1;
         break;
      }


    // blit old image back
      l0 = i2xy(oldLoc)[0];
      l1 = i2xy(oldLoc)[1];

      temp = Game.map.mapArray[l1][l0].split(",");

      if(temp[1] == "empty"){
         var retval = "url(http://www.vegras-studios.com/X/tile/php/blit.php?img=../images/" + temp[0] + ".png)";
      }else{
         var retval = "url(http://www.vegras-studios.com/X/tile/php/transblit.php?img=../images/" + temp[0] + ".png&bg=../images/" + Game.map.bg + ".png&fade=100)";
      }
      document.getElementById(oldLoc).style.background = retval;

    // draw player
      l0 = i2xy(newLoc)[0];
      l1 = i2xy(newLoc)[1];

      temp = Game.map.mapArray[l1][l0].split(",");

[COLOR="Red"]    // update location
      this.loc = newLoc;[/COLOR]
[COLOR="DarkOliveGreen"]/*////// Dit stukje is verplaats, stond eerst onderaan ///////////*/[/COLOR]

    // check trigger
      if(!(temp[1] == "empty")){
         CallTrigger(temp[1]);
      }

      if(Block.block == 1){
[COLOR="Red"]         newLoc = oldLoc;[/COLOR]
    // re-calculate location and temp...
         l0 = i2xy(newLoc)[0];
         l1 = i2xy(newLoc)[1];
         temp = Game.map.mapArray[l1][l0].split(",");
[COLOR="Red"]         this.loc = oldLoc;[/COLOR]
      }



      if(temp[1] == "empty"){
            var retval = "url(http://www.vegras-studios.com/X/tile/php/translocblit.php?x=" + gm_side.x + "&y=" + gm_side.y + "&img=../images/" + Player.facing.graphic + ".png&bg=../images/" + Game.map.bg + ".png&fade=100)";
      }
      document.getElementById(newLoc).style.background = retval;



    // reset block (if?!)
      Block.do(0);


    }
 
Laatst bewerkt:
Glest,

heeeeeel erg bedankt. Het werkt nu goed, behalve de oude tile die grassig blijft, maar daar ga ik morrige aan werken (is niet zo lastig denk ik)

Tsja, logica, soms raak je de draad kwijt :p




:thumb:


ps. meesterlijke handtekening
 
Ik heb het probleem al gevonden :P Ik was even op dreef :D

In de walk functie, bijna helemaal op het einde staat dit:
Code:
      if(temp[1] == "empty"){
            var retval = "url(http://www.vegras-studios.com/X/tile/php/translocblit.php?x=" + gm_side.x + "&y=" + gm_side.y + "&img=../images/" + Player.facing.graphic + ".png&bg=../images/" + Game.map.bg + ".png&fade=100)";
      }
      document.getElementById(this.loc).style.background = retval;

retval is niks als temp[1] != "empty", blijkbaar geeft je php script dan standaard een graslandje. Laatse lijntje in de if-statement zetten en het is weg :)

Code:
      if(temp[1] == "empty"){
            var retval = "url(http://www.vegras-studios.com/X/tile/php/translocblit.php?x=" + gm_side.x + "&y=" + gm_side.y + "&img=../images/" + Player.facing.graphic + ".png&bg=../images/" + Game.map.bg + ".png&fade=100)";
            document.getElementById(this.loc).style.background = retval;
      }


Heel leuk gedaan trouwens, het hele script. Draait prachtig (in Firefox) :thumb:


/edit: Ik herinner nu trouwens dat ik je relatieve urls vervangen heb door absolute urls zodat ik het lokaal kon draaien. Moet je maar negeren :P
 
Laatst bewerkt:
hehe, cool.
ja, dat komt omdat er dan niets over het graslandje wordt geplakt. Het blijft dus gras.


Bedankt, ik wilde het al een tijdje doen, begon met Visual Basic, ging makkelijker (scrollende map, bitblt ftw, etc) maar dit's natuurlijk veel ruimer. En lastiger (voor mij :p).

Ben van plan er wat groters van te maken en dan de source te zippen, dus als iemand er dan iets mee wilt, check 'test mijn programma' in het programeer-subforum!


:thumb:
 
Laatst bewerkt:
Ik heb het enigzins buggy aan de praat gekregen in IE7 en Chrome. IE7 bleef maar zeuren over c_PlayerBlock.do();

Blijkbaar is do() gereserveerd in bijde browsers. Door de functie een andere naam te geven kun je rondlopen, maar als je tegen een muur aan loopt gaat er nog iets fout. Teleporteren werkt wel prima. Het leven is vreemd, maar Javascript is nog vreemder :shocked:
 
Laatst bewerkt:
Okay, een tweede vraag tenopzichte van deze tileengine:

als ik het open in IE6, werkt het niet(goed). Dit was altijd al zo, IE6 schijnt een probleem te hebben met de dynamisch gegenereerde plaatjes (php bestand) en laad deze extreem traag. Opzich niet zo heel erg, maar als iemand een idee heeft, graag.

Wat nu het probleem is is dat bij zowel IE6 als IE7 er sinds de her-scripting naar 'OOP' er een script-error komt, en wel:
Regel 595
Teken: 13
Fout: Id wordt verwacht
Code: 0
URL: http://www.vegras-studios.com/X/Tile/

Nu heb ik egen flauw idee wat ze bedoelen, en zover ik weet is er nergens iets van een functie, variabele of parameter genaamd 'id'. Is dit mischien een GetElementById() fout?

Wat precies regel 595 is weet ik niet, maar de enige file met meer dan 500 regels is test_game_1.js, en dit is de omliggende code:
PHP:
//js

function CallTrigger(trigger)
{
   switch(trigger)
   {

   case "solid":
      Block.do(1);
      break;      // DIT IS REGEL 595
   case "TR_TREE1":
      Block.do(1);
      OutputGame("It's a small tree...");
      break;
   case "TR_SIGN1":
      Block.do(1);
      OutputGame("A sign saying:\n\t'This is fun!'");
      break;
   case "TR_ASH1":
      Block.do(1);
      OutputGame("An ashtray. What's it doing here?'");
      break;


   case "TR_PORT_MAP2":
      Game.updatemap(map2);
      Player.newmap(1);
      break;


   case "TR_PORT_MAP1":
      Game.updatemap(map1);
      Player.newmap(2);
      break;


   }
}

iemand een idee?

:thumb:
 
Je was net te laat (heb het hier boven net gepost) :P Maar het probleem is dus c_PlayerBlock.do(). Je moet de functie een andere naam geven :confused:


/edit: Het werkt zelfs in Opera als je c_Playerblock.do() hernoemt. Maarja, in Opera, IE en Chrome loop je wel door muren heen.

IE geeft de foutmelding: "Game.map.mapArray[...] is leeg of geen object"
 
Laatst bewerkt:
Ik zie het, ga het even veranderen. Bedankt alvast.

:thumb:



edit: Zupah, het werkt nu ook in IE6 en IE7. Laden duurt wel langer dan alle andere browsers, maar toch.

edit-edit: heh, safari is ook blij

edit-edit-edit: Dat je door muren kan lopen komt omdat elke tile wordt gecheckt op do(), maar na hernaming tot doblock(). Sinds de 'triggers' worden gecheckt en daarna met do() de speler wordt geblokkeerd, call je dus naar do() die niet bestaat..... heb t even aangepast, nu werkt het in alle browsers behalve opera!

edit[0,1,2,3]: Dat "Game.map.mapArray[...] is leeg of geen object" krijg je als je buiten de map probeert te lopen (dus door muren), sinds de map-array die items niet heeft geeft het leegheid terug.

meer edit: opera werkt, moest even de cache verwijderen :)
 
Laatst bewerkt:
Oh ik zie het, ik liep door muren heen omdat ik de functie c_playerBlock.do() geleegd had om te kijken of het aan de inhoud lag. Ben alleen vergeten om de inhoud weer terug te zetten nadat ik hem hernoemd had :P Het werkt inderdaad, IE6+7, Chrome, Firefox, Opera. Meer heb ik niet om te testen. Prachtige engine :thumb:

/edit: Bij mij werkt het ook in opera. Alleen je moet steeds opnieuw op een pijltjes toets drukken. Dat komt doordat Opera onkeydown maar één keer vuurt. onkeypress werkt wel hetzelfde in opera als in de andere, maar officeel is onkeypress niet bedoeld voor pijltjes toesten.
 
Laatst bewerkt:
Thanks again :D :D

Vraag helemaal opgelost.


Voor de mensen die er zin in hebben:

Wat nu nog rest in mijn want-lijstje is het loop-animatie van 'TestGuy' (aka Ash uit pokemon :p)

In VB kon ik het altijd gewoon 8 px. verder de 'been-vooruit' image blitten, maar hier zit ik met 16px vast. In het divje dat verder zit heb ik wel eens geprobeert om het in het nieuwe locatie-divje te doen, maar dat ziet er gek uit. Bovendien ga je bij te snel lopen een spoor van players achterlaten :p Zie http://www.vegras-studios.com/x/tile/xDEV/BLACKUPS/27-10.17-39/ (!!! firefox only weer geloof ik)

Iemand een idee voor een loop-animatie? Zat eraan te denken de 2 div's te pakken, dan een halve player op de 1, halve op de andere (lang leve php's copymerge) maar dit is mischien wat onhandig/intensief. Iemand een ander idee?


:thumb:






/edit: Bij mij werkt het ook in opera. Alleen je moet steeds opnieuw op een pijltjes toets drukken. Dat komt doordat Opera onkeydown maar één keer vuurt. onkeypress werkt wel hetzelfde in opera als in de andere, maar officeel is onkeypress niet bedoeld voor pijltjes toesten.
Tsja, ik zat in het begin zowiezo te bliep-en met die pijltjes (ff/ie, which vs KeyCode) dus was allang blij dat het werkte. Mischien als het wat wordt dat ik iets ga zoeken voor die pijltjes, maar voor nu is het wel goed zo :p iig bedankt voor de opmerking, ik had het niet gemerkt.
 
Laatst bewerkt:
Als je je ventje splits over twee divs, dan loopt je ventje dus steeds een halve tile? Dan kan het wel.

Als je een hele tile loopt maar wel twee frames af wilt spelen dan moet je met timeouts gaan werken om ervoor te zorgen dat de animatie afgespeeld wordt lijkt mij. En dat is niet echt fijn.

Ik zou steeds een halve tile lopen en elke halve tile de frame verwisselen. Dan moet je positie dus niet meer in tiles staan, maar in halve tiles. De tile waar de player zich bevindt wordt dan dus math.Floor(Player.pos/2). Maar dat hoef ik je waarschijnlijk niet te vertellen :p


/edit: Ik weet nu trouwens niet meer zeker of onkeypress echt gelimiteerd is tot input keys (a-z0-9 etc). De laatste W3C DOM specificatie vermeldt dit. Het hangt dus compleet van de browser af hoe het geimplementeerd is.
1.6.3. Key events

The DOM Level 2 Event specification does not provide a key event module. An event module designed for use with keyboard input devices will be included in a later version of the DOM specification.
 
Laatst bewerkt:
Als je een hele tile loopt maar wel twee frames af wilt spelen dan moet je met timeouts gaan werken om ervoor te zorgen dat de animatie afgespeeld wordt lijkt mij. En dat is niet echt fijn.

Ik zou steeds een halve tile lopen en elke halve tile de frame verwisselen. Dan moet je positie dus niet meer in tiles staan, maar in halve tiles.

Ja, de link die ik plaatste is van n oude versie die met n timeout werkt. Zoals je ziet, buggy, maar dit kwam ook omdat het niet lukte om BlockKeys() te gebruiken, wat in die versie dus ook niet klopte. (nieuwe versie heeft t nog niet).

Player halve frames laten zijn, tsja. Zoals je zelf al zei, dat is meer wiskunde dan dat het nu is en bovendien wordt het lastig met triggers denk ik. Ook zijn objecten dan lastig (nu is er tegen aanlopen goed, maar dan krijg je dat je een halve tile loopt en er dan pas tegenaan loopt...)

Het worden toch maar timeouts denk ik :p



:thumb:
 
Laatst bewerkt:
Je kunt misschien ook gewoon hele tiles lopen en de animatie per tile afwisselen. Het kan er niet vreemder uitzien dan eerst verplaatsen en dan je benen bewegen :P En het is simpel
 
Het kan er niet vreemder uitzien dan eerst verplaatsen en dan je benen bewegen
eigenlijk wel, want 'normaal' (lees: in de 'echte' game :p) krijg je EN zoals je zelf al zei, afwisselende benen, EN je beweegt 2x 8 pixels met zo'n 250 ms timeout. iets als dit:
PHP:
//js

//animatie naar links toe:

BeweegLinkerbeen()
MoveToLeft(8px)
Wacht(150)

LaatNormaalZien()
Wacht(50)

BeweegRechterbeen()
MoveToLeft(8px)
Wacht(150)


Maargoed, dat komt nog wel eens. Iig bedankt voor het meedenken!
:thumb:
 
Laatst bewerkt:
ah ik zie, dus dan moet je alleen voorkomen dat je beweegt (een keypress gehandled wordt) voordat de animatie klaar is. En daar is BlockKeys(); voor. Dan moet je nog wel over halve tiles gaan werken, maar dat valt niet uit te sluiten dus.

Ik werk zelf niet graag met timeouts. Ze verstoren de logische volgorde van de code. Maarja, het is niet altijd te vermijden. En als je verdere input blokkeert tot de timeout klaar is, dan zou het geen problemen moeten geven.

Of, maar dat lijkt me geen goed plan, je kunt je hele systeem omgooien en je tiles half zo breed en half zo hoog maken :P Maar dan zouden objecten van nu één tile dus 4 tiles in beslag moeten nemen, en nog een hoop meer vervelende veranderingen. Dus ik houd mijn mond al :o
 
Laatst bewerkt:
yup, dat dacht ik ook :)

En timeouts moet/ga ik zowiezo wel gebruiken, sinds sommige tiles beweegbaar gaan zijn (water bijvoorbeeld). Maar dat is weer een ander verhaal.

Denk dat het handiger is als suggesties etc. in het topic dat ik voor de engine heb aangemaakt, hier: http://www.helpmij.nl/forum/showthread.php?t=383870 gaan komen.


:thumb:
 
Status
Niet open voor verdere reacties.

Nieuwste berichten

Terug
Bovenaan Onderaan