Box2D for Flash og AS3: Punktgrafikk og Boxes

Box2D for Flash og AS3: Punktgrafikk og bokser
Del
Del
5
Del

Denne Cyber ​​Monday Envato Tuts + kurs vil bli redusert til bare $ 3. Ikke gå glipp av.

I første del av denne serien, dekket vi grunnleggende for Box2D, ved å legge noen enkle sirkulære objekter og gjengi dem ved hjelp av grafikk samtaler. I denne delen, vil vi ikke bare bruke bilder som skal representere våre gjenstander, vil vi lære å bruke en helt annen form, også!


Jeg anbefaler å lese denne serien fra starten , men hvis du ønsker å begynne her, så grip denne zip-filen - den inneholder kildekoden vi skrev i den første delen. (. Last ned
knappen ovenfor inneholder kildekoden fra slutten av denne
del)



Trinn 1: Sett Dette PNG i ditt prosjekt

Vi begynner ved å erstatte vanlig sirkler som vi har brukt med noe annet. Høyreklikk på denne PNG å laste den ned til din harddisk:

(Det blir god tid til å tegne dine egne design senere, men for nå, bare ta denne.)

Legg det til prosjektfiler.

I Flash Pro, betyr dette å importere den til biblioteket, og gi den et navn Class (plukke SimpleWheelBitmapData). I FlashDevelop betyr dette å sette den i bibliotek
mappe, og bygge det inn i hovedklassen ved hjelp av kode som så: product: [Embed (kilde = '.. /lib /SimpleWheel.png')] offentlig Var SimpleWheel: Klasse;

Gjør hva er relevant for arbeidsflyten. Jeg oppretter en Pure AS3 Project i FlashDevelop, huske, så jeg skal skrive i den sammenheng



Trinn 2:. Lag en Array å holde hjulet Images

For hvert hjul som vi skaper i Box2D verden, må vi opprette en forekomst av SimpleWheel og legg den i visningslisten. Å få tilgang til alle disse hjulene, kan vi bruke en annen array - lage et, og kaller det wheelImages []:
offentlige Var wheelImages: Array;

Pass på at du initialisere den nær toppen av getStarted (), samt :
privat funksjon getStarted (): void {var Vekt: b2Vec2 = new b2Vec2 (0, 10); verden = new b2World (gravitasjon, true); wheelArray = new Array (); wheelImages = new Array ();



Trinn 3: Starte Wheel Images

Det mest fornuftig sted å initial bildene av hjulene er i createWheel (), siden vi har alle argumentene vi trenger

Legg disse linjene til slutten av denne funksjonen.
wheelArray.push (wheelBody); Var wheelImage: Bitmap = new SimpleWheel (); wheelImage.width = radius * 2; wheelImage.height = radius * 2; wheelImage.x = startx; wheelImage.y = starty; this.addChild (wheelImage); wheelImages.push (wheelImage);.}

Se opp - du trenger å importere flash.display.Bitmap også, siden den PNG vi innebygd er en Bitmap

Hvis du bruker Flash Pro, så du ikke har en SimpleWheel klasse, så i stedet for å skrive ny SimpleWheel (), må du gjøre dette:
wheelArray.push (wheelBody); Var wheelImage: Bitmap = new Bitmap (ny SimpleWheelBitmapData ()); wheelImage.width = radius * 2; wheelImage.height = radius * 2; wheelImage.x = startx; wheelImage.y = starty; this.addChild (wheelImage); wheelImages.push (wheelImage);}

(Jeg kommer til å fortsette å bruke ny SimpleWheel () gjennom denne opplæringen, for enkelhet Bare husk at du må endre det hvis du bruker Flash Pro..)
< p> Du kan prøve dette ut allerede! Hjulene vil ikke flytte, men de bør være på skjermen (tross alt, de er på listen display). Her er mine (klikk for å spille):

Oh. Um. Hvor er de



Trinn 3: Forestillinger om Betegnelser

Problemet her er at skalafaktoren igjen. Husk: Box2D tar målinger i meter, mens Flash tar mål i piksler. Radien parameteren er i meter, mens startx og starty parametere er i pixler; vi ikke å bruke en skaleringsfaktor til heller, vil du legge merke til, så vi er ikke ser de resultatene vi forventer. (I dette tilfellet blir bildet blir gjort så høy og så bred at alt du kan se er i øverste venstre hjørne -. Som er full av gjennomsiktige piksler)

Vi kan bestemme seg for å standardisere på en eller de andre målesystemer, f.eks å spesifisere alle mål i meter fra nå av, slik at vi vet at vi alltid må multiplisere med skalafaktoren for eventuelle Flash funksjoner som krever piksler ... men, jeg skal være ærlig, jeg kommer til å finne dette en smerte. I stedet foreslår jeg at vi bruker en form for ungarske notasjon (den gode typen) for å stoppe oss å bli forvirret

Det er en enkel idé. Vi bare gi alle våre variabler som er målt i meter navn som begynner med m, og alle våre variabler som er målt i piksler som begynner med px (du kan velge forskjellige prefikser hvis du bruker m og px å bety forskjellige ting i koden). Sjekk det ut:
privat funksjon createWheel (mRadius: Antall, pxStartX: Antall, pxStartY: Antall, mVelocityX: Antall, mVelocityY: Number): void {var wheelBodyDef: b2BodyDef = new b2BodyDef (); wheelBodyDef.type = b2Body.b2_dynamicBody; wheelBodyDef.position.Set (pxStartX /skalafaktoren, pxStartY /skalafaktoren); Var wheelBody: b2Body = world.CreateBody (wheelBodyDef); Var circleShape: b2CircleShape = new b2CircleShape (mRadius); Var wheelFixtureDef: b2FixtureDef = new b2FixtureDef (); wheelFixtureDef.shape = circleShape; wheelFixtureDef.restitution = (Math.random () * 0,5) + 0,5; wheelFixtureDef.friction = (Math.random () * 1,0); wheelFixtureDef.density = Math.random () * 20; Var wheelFixture: b2Fixture = wheelBody.CreateFixture (wheelFixtureDef); Var startingVelocity: b2Vec2 = new b2Vec2 (mVelocityX, mVelocityY); wheelBody.SetLinearVelocity (startingVelocity); wheelArray.push (wheelBody); Var wheelImage: Bitmap = new SimpleWheel (); wheelImage.width = mRadius * 2; wheelImage.height = mRadius * 2; wheelImage.x = pxStartX; wheelImage.y = pxStartY; this.addChild (wheelImage); wheelImages.push (wheelImage);}

See? Nå kan vi kjapt fortelle at wheelImage.width = mRadius * 2 er feil, fordi wheelImage.width er en Flash Displayobject eiendom, noe som betyr at den forventer piksler, men mRadius er selvsagt i meter. For å fikse dette, må vi bruke skalaen faktoren - men det er vanskelig å huske, uten å se det opp, om vi trenger å dele eller multiplisere, rett

Svaret er formere, men vi kan gjøre dette? enklere ved å døpe skalafaktoren fra skalafaktoren til mToPx ("meter til piksler"). Gjøre en "finne /erstatte" i koden din, slik at du ikke går glipp av noen.

Så, nå vet vi at vi kan multiplisere noen verdi i meter ved mToPx å få tilsvarende verdi i piksler. Det er ikke så vanskelig å huske at du kan dele denne for å gjøre det motsatte, men for å gjøre det enda enklere, la oss lage en variabel pxToM som gjør det omvendte - dvs. når du multiplisere en piksel måling av pxToM, får du tilsvarende måling i meter.

Vi kan gjøre dette ved å bare lage en ny variabel der verdien er en delt mToPx, fordi anyValue * (1 /mToPx) == anyValue /mToPx. Så:
offentlig Var mToPx: Number = 20; offentlig Var pxToM: Number = 1 /mToPx;

Nå bare gjøre en annen "finne /erstatte" endre "/mToPx" til "* pxToM" overalt i koden . Er, men sørg for at du skrive om linjen vi nettopp lagt, som sier offentlig Var pxToM: Number = 1 /mToPx

Test din SWF å sikre at det fortsatt kjører som du forventer. Antar det er, det er flott! Det betyr at alt du trenger å huske er at du aldri dele av en skaleringsfaktor
. Bare formere seg. Flash er raskere ved å multiplisere, uansett

Ok, nå kan vi faktisk bruke skalaen faktor til createWheel () koden vi hadde problemer med:
Var wheelImage. Bitmap = new SimpleWheel (); wheelImage.width = mRadius * 2 * mToPx; wheelImage.height = mRadius * 2 * mToPx; wheelImage.x = pxStartX; wheelImage.y = pxStartY; this.addChild (wheelImage); wheelImages.push (wheelImage);}

Prøv det ut:

Cool! Nå kan vi se PNGs, selv om de ikke beveger seg ennå. Alt det arbeidet vi gjorde for å endre notasjon kan ha virket unødvendig, men tro meg, hvis du ikke gjør det nå, ville du ønske du hadde senere



Trinn 4:. Gjør Hjul Flytt

Som du husker fra den første delen av denne serien, selve bevegelsen av hjulene er håndtert i onTick () -funksjonen. Her er hva nøkkelkoden ser ut nå:
for hver (var wheelBody: b2Body i wheelArray) {graphics.drawCircle (wheelBody.GetPosition () x * mToPx, wheelBody.GetPosition () y * mToPx, (wheelBody... . GetFixtureList () GetShape () som b2CircleShape) .GetRadius () * mToPx);}

Kommentar ut sirkelen tegning kode, og erstatte den med kode for å flytte riktig bilde fra tabellen:
Var wheelImage: Bitmap; for hver (var wheelBody: b2Body i wheelArray) {/* graphics.drawCircle (wheelBody.GetPosition () x * mToPx, wheelBody.GetPosition () y * mToPx, (wheelBody.GetFixtureList () GetShape () som b2CircleShape... ) .GetRadius () * mToPx); * /WheelImage = wheelImages [wheelArray.indexOf (wheelBody)]; wheelImage.x = wheelBody.GetPosition () x * mToPx.; wheelImage.y = wheelBody.GetPosition () y * mToPx;.}

(Siden hvert bilde er lagt til wheelImages [] når tilsvarende kroppen er lagt til wheelArray [], da vet vi at, uansett hvilken posisjon kroppen er i wheelArray [], må bildet være i samme posisjon i wheelImages [])

Prøv det ut.?

Det er bra, men hvorfor er de hjulene alt halvparten underground
< hr>
Trinn 5: den synkende følelsen

Vi vet at sirkelen-tegning kode fra før fungerer fint, så la oss un-kommentere det å se om det gir oss noen ledetråder:
Var wheelImage : Bitmap, for hver (var wheelBody: b2Body i wheelArray) {graphics.drawCircle (wheelBody.GetPosition () x * mToPx, wheelBody.GetPosition () y * mToPx, (wheelBody.GetFixtureList () GetShape () som b2CircleShape... ) .GetRadius () * mToPx); wheelImage = wheelImages [wheelArray.indexOf (wheelBody)]; wheelImage.x = wheelBody.GetPosition () x * mToPx.; wheelImage.y = wheelBody.GetPosition () y * mToPx;.?}

Hjelper det

Ja. Klart, er PNG-bilder forskjøvet fra selve objektenes posisjoner.

Dette er fordi Box2D koordinater er gitt fra sentrum av sirkelen former. Når vi trekker dem med graphics.drawCircle () har vi ingen problemer, fordi den funksjonen trekker sirkler fra sine sentre; Men når vi setter x og y egenskapene til en Displayobject, Flash stillinger det basert på sin registreringspunktet Anmeldelser - og, som standard, er vår SimpleWheel registreringspunkt øverst til venstre i PNG.

Løsningen er enkel, men: vi må bare flytte bildet for å kompensere for dette utlignet. Øverst i venstre hjørne av bildet er i sentrum av objektet, så vi trenger å flytte den opp og til venstre, slik at midten justeres:
Var wheelImage: Bitmap, for hver (var wheelBody: b2Body i wheelArray) { graphics.drawCircle (wheelBody.GetPosition () x * mToPx, wheelBody.GetPosition () y * mToPx, (wheelBody.GetFixtureList () GetShape () som b2CircleShape) .GetRadius () * mToPx...); wheelImage = wheelImages [wheelArray.indexOf (wheelBody)]; wheelImage.x = (wheelBody.GetPosition () x * mToPx.) - (wheelImage.width * 0,5); wheelImage.y = (. wheelBody.GetPosition () y * mToPx) - (wheelImage.height * 0,5);}

Forskyvning det halve bredden og høyden bør gjøre triks. Prøv det:

Ordnet. Kommentar ut grafikk tegning koden på nytt og prøve en høyere skala faktor (la oss gå med mToPx = 40)



Trinn 6:. Detect klikk

Nå som vi setter gjenstander på listen displayet, kan vi kommunisere med dem ved hjelp av musen. En veldig enkel måte å demonstrere dette på er å gi hjulene litt "push" når de er klikket.

Før vi kommer inn i fysikken kode for det, la oss sørge for at vi kan oppdage hvilken boks ble klikket. Legg en MouseEvent.CLICK lytter til hvert hjul bilde, ved å sette inn denne koden på slutten av createWheel ():
wheelImage.addEventListener (MouseEvent.CLICK, onClickWheelImage);

Ikke glem å importere flash.events. MouseEvent. Nå oppretter behandleren funksjon (Jeg har lagt et spor til å sjekke det fungerer):
privat funksjon onClickWheelImage (event: MouseEvent): void {trace ("Et hjul ble klikket");}

Prøv det ut. Ikke virker? Oh, det er fordi Bitmap ikke stige ned fra InteractiveObject (som oppdager mus hendelser). Det er frustrerende. Det er lett å fikse, skjønt; vi bare pakk hver Bitmap i en Sprite, inne createWheel ():
Var wheelImage: Bitmap = new SimpleWheel (); wheelImage.width = mRadius * 2 * mToPx; wheelImage.height = mRadius * 2 * mToPx; //wheelImage .x = pxStartX; < - slette denne //wheelImage.y = pxStartY; < - slette denne //this.addChild (wheelImage); < - slett thisvar wheelSprite: Sprite = new Sprite (); wheelSprite.addChild (wheelImage); wheelSprite.x = pxStartX; wheelSprite.y = pxStartY;wheelImages.push(wheelSprite);this.addChild(wheelSprite);wheelSprite.addEventListener(MouseEvent.CLICK, onClickWheelImage);

... og deretter i onTick (), kan vi ikke kaste wheelImage til en Bitmap lenger, må vi definere det som en Sprite:
privat funksjon onTick (a_event: Timerevent): void {//graphics.clear (); graphics.lineStyle (3, 0xff0000); world.Step (0,025, 10, 10); //Var wheelImage: Bitmap; < - slette dette Var wheelImage: Sprite;

Koden for som ser slik ut:
Var crateBodyDef: b2BodyDef = new b2BodyDef (); crateBodyDef.position.Set (mStartX, mStartY); Var crateBody: b2Body = world.CreateBody (crateBodyDef); Var crateShape: b2PolygonShape = new b2PolygonShape (); crateShape.SetAsBox (mWidth /2, mHeight /2); Var crateFixtureDef: b2FixtureDef = new b2FixtureDef (); crateFixtureDef.shape = crateShape; Var crateFixture: b2Fixture = crateBody.CreateFixture (crateFixtureDef);

(Husk at SetAsBox () metoden tar halvparten
-Bredde og halvparten
-Høyde, så vi må dele på to. )

La oss bryte det opp i en funksjon, som vi gjorde med createWheel ():
privat funksjon createCrate (mWidth: Antall, pxStartX: Antall, pxStartY: Antall, mVelocityX: Antall, mVelocityY: Number) : void {var crateBodyDef: b2BodyDef = new b2BodyDef (); crateBodyDef.position.Set (pxStartX * pxToM, pxStartY * pxToM); //oppmerksom skalafaktoren Var crateBody: b2Body = world.CreateBody (crateBodyDef); Var crateShape: b2PolygonShape = new b2PolygonShape (); crateShape.SetAsBox (mWidth /2, mWidth /2); //kasser er firkantet så bredde == høyde Var crateFixtureDef: b2FixtureDef = new b2FixtureDef (); crateFixtureDef.shape = crateShape; Var crateFixture: b2Fixture = crateBody.CreateFixture (crateFixtureDef); Var startingVelocity: b2Vec2 = new b2Vec2 (mVelocityX, mVelocityY); crateBody.SetLinearVelocity (startingVelocity);}

Se opp - koden er litt forskjellig fra det som ovenfor. Siden vi brukte piksel målinger for å velge posisjonene av hjulene, har jeg anvendt punktmålinger for stillingen av kassen, også. Også, siden kassene er kvadratisk, jeg har ikke tatt en mHeight parameter. Og jeg har satt hastigheten, bruker stort sett den samme koden som for hjulene.

Ja, ja, vi kan faktisk ikke se dem med mindre vi bruker grafikk samtaler eller legge til noen tilfeller av SimpleCrate eller hva, jeg kjenne til. Men vi kan i det minste se deres effekter, så prøv å legge en nå:
privat funksjon getStarted (): void {var Vekt: b2Vec2 = new b2Vec2 (0, 10); verden = new b2World (gravitasjon, true); wheelArray = new Array (); wheelImages = new Array (); for (var i: int = 0; i < 20; i ++) {createWheel (Math.random () * 0,5, Math.random () * (stage.stageWidth - 20) + 10, Math.random () * ( stage.stageHeight - 20) + 10, (Math.random () * 100) - 50, 0); createCrate (Math.random () * 0,5, Math.random () * (stage.stageWidth - 20) + 10, Math.random () * (stage.stageHeight - 20) + 10, (Math.random () * 100 ) - 50, 0)} createBoundaries (); stepTimer = new Timer (0,025 * 1000); stepTimer.addEventListener (TimerEvent.TIMER, onTick); graphics.lineStyle (3, 0xff0000); stepTimer.start ();}

Prøv det ut:

Det fungerer, men noe er ikke helt rett. Antar vi må gjøre dem synlige for å finne ut hva



Trinn 10:. Se Kasser

Som før, vil vi gjøre en matrise for å holde buret organer, og annen rekke for å holde buret grafikk:
offentlig Var verden: b2World; offentlig Var wheelArray: Array, offentlige Var wheelImages: Array, offentlige Var crateArray: Array, offentlige Var crateImages: Array, offentlige Var stepTimer: Timer, offentlige Var mToPx : Number = 50; offentlig Var pxToM: Number = 1 /mToPx; /** klipp ** /privat funksjon getStarted (): void {var Vekt: b2Vec2 = new b2Vec2 (0, 10); verden = new b2World (gravitasjon, true); wheelArray = new Array (); wheelImages = new Array (); crateArray = new Array (); crateImages = new Array ();

Deretter må vi fylle disse matriser:
privat funksjon createCrate (mWidth: Antall, pxStartX: Antall, pxStartY: Antall, mVelocityX: Antall, mVelocityY: Number): void {var crateBodyDef: b2BodyDef = new b2BodyDef (); crateBodyDef.position.Set (pxStartX * pxToM, pxStartY * pxToM); //oppmerksom skalafaktoren Var crateBody: b2Body = world.CreateBody (crateBodyDef); Var crateShape: b2PolygonShape = new b2PolygonShape (); crateShape.SetAsBox (mWidth /2, mWidth /2); //kasser er firkantet så bredde == høyde Var crateFixtureDef: b2FixtureDef = new b2FixtureDef (); crateFixtureDef.shape = crateShape; Var crateFixture: b2Fixture = crateBody.CreateFixture (crateFixtureDef); Var startingVelocity: b2Vec2 = new b2Vec2 (mVelocityX, mVelocityY); crateBody.SetLinearVelocity (startingVelocity); crateArray.push (crateBody); Var crateImage: Bitmap = new SimpleCrate (); //eller "ny Bitmap (ny SimpleCrateBitmapData ());" i Flash Pro crateImage.width = mWidth * mToPx; crateImage.height = mWidth * mToPx; Var crateSprite: Sprite = new Sprite (); crateSprite.addChild (crateImage); crateSprite.x = pxStartX; crateSprite.y = pxStartY; crateImages.push (crateSprite); this.addChild (crateSprite);}

Dette er egentlig den samme koden som for gjengivelse av hjulet, men med endringer i bredden og høyden fordi kasse er firkantet, ikke rund. Bildene er i listevisning, men vi må gjøre dem flytte hver tick, så legg dette til onTick () -funksjonen:
Var crateImage: Sprite, for hver (var crateBody: b2Body i crateArray) {crateImage = crateImages [crateArray.indexOf (crateBody)]; crateImage.x = (crateBody.GetPosition () x * mToPx.) - (crateImage.width * 0,5); crateImage.y = (. crateBody.GetPosition () y * mToPx) - (crateImage.height * 0,5);}

Her er resultatet:

De kassene ikke er i bevegelse! Det forklarer hvor merkelig. Vet hvorfor? Det er fordi jeg har glemt noe ... har en gjetning på hva, deretter utvide boksen under for å se om du har rett
privat funksjon createCrate (mWidth. Antall, pxStartX: Antall, pxStartY: Antall, mVelocityX: Antall, mVelocityY: Number): void {var crateBodyDef: b2BodyDef = new b2BodyDef (); crateBodyDef.type = b2Body.b2_dynamicBody; crateBodyDef.position.Set (pxStartX * pxToM, pxStartY * pxToM); Var crateBody: b2Body = world.CreateBody (crateBodyDef); Var crateShape: b2PolygonShape = new b2PolygonShape (); crateShape.SetAsBox (mWidth /2, mWidth /2); Var crateFixtureDef: b2FixtureDef = new b2FixtureDef (); crateFixtureDef.shape = crateShape; Var crateFixture: b2Fixture = crateBody.CreateFixture (crateFixtureDef);

Prøv nå:

Problem løst! La oss gjøre kassene litt større, også:
for (var i: int = 0; i < 20; i ++) {createWheel (Math.random () * 0,5, Math.random () * (stage.stageWidth - 20) + 10, Math.random () * (stage.stageHeight - 20) + 10, (Math.random () * 100) - 50, 0); createCrate (Math.random () * 1,5, Math.random () * (stage.stageWidth - 20) + 10, Math.random () * (stage.stageHeight - 20) + 10, (Math.random () * 100 ) - 50, 0)}

Det er bedre



Trinn 11: The Amazing Balancing Crate

Jeg la merke til noe rart.. Prøv å balansere en stor kasse på et lite hjul, som så: Twitter /* for (var i: int = 0; i < 20; i ++) {createWheel (Math.random () * 0,5, Math.random () * (stage.stageWidth - 20) + 10, Math.random () * (stage.stageHeight - 20) + 10, (Math.random () * 100) - 50, 0); createCrate (Math.random () * 1,5, Math.random () * (stage.stageWidth - 20) + 10, Math.random () * (stage.stageHeight - 20) + 10, (Math.random () * 100 ) - 50, 0)} * ///lage disse objektene spesifikt, i stedet for å generere hjulene og kasser tilfeldig: createWheel (0,5, stage.stageWidth /2, stage.stageHeight - (0,5 * mToPx), 0, 0); createCrate (3,0, (1,0 * mToPx) + stage.stageWidth /2, stage.stageHeight - (3,5 * mToPx), 0, 0);

Odd, ikke sant? En kasse bør ikke balansere på en rund gjenstand sånn. Hvis du klikker på hjulet for å gjøre det rulle unna, kasse faller bare rett ned (eller, noen ganger, følger hjulet)

Det gjør det føles som om massen av kassen er ujevnt fordelt -. Som den inneholder noe virkelig, virkelig tung, alt i sin venstre side, som la det balansere på rattet

Faktisk er problemet å gjøre med sin masse. vi ikke gi den noe! Box2D gjør gi et organ en standard masse hvis ingen er spesifisert, men det finnes andre masserelaterte egenskaper (som treghetsmoment) som ikke får satt riktig i dette tilfellet, slik at kroppen handle merkelig.

Ikke bry deg om hva disse egenskapene er for nå - bare vet at for å løse dem, trenger vi å gi hver kroppen en skikkelig masse. Vel, faktisk, for å kontrollere at alt oppfører seg slik vi forventer det til, bør vi i stedet sette massen av individuelle kamper, og la Box2D finne ut massen av kroppen selv. Og i stedet for å sette massen direkte, bør vi sette tetthet.
- Det vil si hvor mange kilo en kvadratmeter av ligaen ville veier

Selv om dette høres komplisert, er det faktisk bare betyr å legge en linje:
privat funksjon createCrate (mWidth: Antall, pxStartX: Antall, pxStartY: Antall, mVelocityX: Antall, mVelocityY: Number): void {var crateBodyDef: b2BodyDef = new b2BodyDef (); crateBodyDef.type = b2Body.b2_dynamicBody; crateBodyDef.position.Set (pxStartX * pxToM, pxStartY * pxToM); Var crateBody: b2Body = world.CreateBody (crateBodyDef); Var crateShape: b2PolygonShape = new b2PolygonShape (); crateShape.SetAsBox (mWidth /2, mWidth /2); Var crateFixtureDef: b2FixtureDef = new b2FixtureDef (); crateFixtureDef.shape = crateShape; crateFixtureDef.density = 1,0; //større antall = tyngre objekt Var crateFixture: b2Fixture = crateBody.CreateFixture (crateFixtureDef);

Vi har faktisk allerede satt dette i hjulene! Likevel er det interessant å se hvordan ting oppfører seg annerledes uten disse grunnleggende egenskaper, rett

Test det ut nå:?

Hmm ... det er bedre, men fortsatt ikke føles helt riktig. Prøv å spille av SWF et par ganger, og du vil se hva jeg mener



Trinn 12:. La noen andre gjøre det harde arbeidet

Når noe ikke føles helt rett i den første delen av denne opplæringen (etter å ha lagt rattet grafikk), vi gikk tilbake til våre eksisterende grafikk tegning kode - som vi visste jobbet -. og så hva problemet var

Dessverre, vi don 't har noen kode for tegning rektangler, enn si kode som vi vet allerede fungerer. Heldigvis gjør Box2D har en slik kode. Det heter DebugDraw

Importer klassen Box2D.Dynamics.b2DebugDraw, deretter endre getStarted () slik:
privat funksjon getStarted (): void {var gravitasjon: b2Vec2 = new b2Vec2 (0, 10); verden = new b2World (gravitasjon, true); Var debugDraw: b2DebugDraw = new b2DebugDraw (); Var debugSprite: Sprite = new Sprite (); addChild (debugSprite); debugDraw.SetSprite (debugSprite); debugDraw.SetDrawScale (mToPx); debugDraw.SetFlags (b2DebugDraw.e_shapeBit); world.SetDebugDraw (debugDraw);

Dette skaper et objekt kalt debugDraw som skal se på alle likene i verden og trekke dem i den nye Sprite vi opprettet, kalt debugSprite. Vi passerer det b2DebugDraw.e_shapeBit å fortelle det at det skal tegne figurene (vi kunne fortelle det bare å tegne, sier sentrene massen av likene i stedet, hvis vi ønsket).

Vi må manuelt Fortell verden for å fortelle DebugDraw objekt å gjengi likene, så gjør dette i onTick ():
privat funksjon onTick (a_event: Timerevent): void {world.Step (0,025, 10, 10); world.DrawDebugData ();

(. Du kan bli kvitt all grafikken kaller nå, vi trenger ikke dem noe mer)

Prøv dette:

Har du sett den? Her er et skjermbilde som viser problemet:

Kroppen roterer, men bildet er ikke. Og - selvfølgelig er det ikke! Vi har aldri fortalt det til



Trinn 13: Like a Record, Baby

Vi kan rotere bildet av kassen ved å sette sin rotasjon eiendom i onTick ():
for hver (var crateBody: b2Body i crateArray) {crateImage = crateImages [crateArray.indexOf (crateBody)]; crateImage.x = (crateBody.GetPosition () x * mToPx.) - (crateImage.width * 0,5); crateImage.y = (. crateBody.GetPosition () y * mToPx) - (crateImage.height * 0,5); crateImage.rotation = crateBody.GetAngle ();}

... vel, ok, det er ikke sant; akkurat som hvordan Box2D bruker meter og Flash bruker for avstandsmålinger piksler, Box2D og Flash bruke ulike enheter for vinkler: radianer i Box2D sak, grader i Flash-tallet. Sjekk denne artikkelen for en full forklaring

For å håndtere dette, vil vi lage et par "vinkel faktor" variabler:
offentlig Var mToPx: Number = 50; offentlig Var pxToM. Number = 1 /mToPx; offentlig Var radToDeg: Antall = 180 /b2Settings.b2_pi; offentlig Var degToRad: Number = b2Settings.b2_pi /180;

Du må importere Box2D.Common.b2Settings - og, igjen, sjekk denne artikkelen Hvis du ønsker å vite hvorfor vi bruker Pi og 180.

Nå bare endre rotasjonen av bildet i onTick ():
for hver (var crateBody: b2Body i crateArray) {crateImage = crateImages [crateArray.indexOf (crateBody)]; crateImage.x = (crateBody.GetPosition () x * mToPx.) - (crateImage.width * 0,5); crateImage.y = (. crateBody.GetPosition () y * mToPx) - (crateImage.height * 0,5); crateImage.rotation = crateBody.GetAngle () * radToDeg;}

Prøv det ut:

... oh



Trinn 14: Opp og til venstre

Her er problemet: kasse image roterer rundt et visst punkt i bildet, kalt registreringspunkt. Kasselegemet roterer rundt et visst punkt i legemet, kalt massesentrum. Disse to punktene er ikke det samme - bortsett fra i en stilling hvor kassen ikke har rotert i det hele tatt

Denne animasjonen viser forskjellen.

kasselegemet roterer rundt sitt sentrum; kasse image roterer rundt ett av hjørnene (den som starter øverst til venstre)

Hvis du bruker Flash Pro, det er en veldig enkel måte å fikse dette. bare endre registreringspunktet ditt kasse symbol til det nøyaktige sentrum av plassen. Hvis du ikke er, men vil du trenger å gjøre tilsvarende ting med kode. Det er fortsatt ganske enkel, men fordi selve kasse Bitmap er inne i en Sprite; når vi roter kasse bilde, vi faktisk roterende som Sprite, som igjen roterer Bitmap inni den

Se, på minuttet, det er som dette.

Den grå stiplede firkanten representerer Sprite som inneholder kasse Bitmap. Den lille grå sirkelen er punktet rundt som Sprite roterer. Hvis vi roter Sprite 90 grader:

... det gjør dette, som du forventer fra å se på Sprite. Men hvis alt du kan se er kasse, ser det ut som det er rotert slik:

See? Nå antar vi flytte kasse Bitmap litt innen
Sprite, slik at sentrene stille opp:

... og vi roter Sprite:

. ..The kasse synes å ha rotert rundt sin senter:

Perfekt! Så, for å gjøre dette arbeidet, trenger vi bare å flytte kasse Bitmap, innenfor Sprite, oppover til det halve sin høyde og forlot halve bredden. Gjør dette ved å endre koden i createCrate ():
Var crateImage: Bitmap = new SimpleCrate (); crateImage.width = mWidth * mToPx; crateImage.height = mWidth * mToPx; Var crateSprite: Sprite = new Sprite (); crateSprite.addChild (crateImage); crateImage.x - = crateImage.width /2; crateImage.y - = crateImage.height /2; crateSprite.x = pxStartX; crateSprite.y = pxStartY; crateImages.push (crateSprite); dette. addChild (crateSprite);

Vi trenger også å fjerne denne koden fra onTick () som flytter kasse Sprite igjen av halvparten av sin bredde og opp til det halve høyden:
Var crateImage: Sprite, for hver (var crateBody: b2Body i crateArray) {crateImage = crateImages [crateArray.indexOf (crateBody)]; (. crateBody.GetPosition () x * mToPx) //husk dette er Sprite, ikke Bitmap crateImage.x =; //- (crateImage.width * 0,5); crateImage.y = (crateBody.GetPosition () y * mToPx.); //- (crateImage.height * 0,5); crateImage.rotation = crateBody.GetAngle () * radToDeg;}

Prøv det ut nå:

Great! Du kan ikke engang se DebugDraw bildet, noe som betyr at det er perfekt dekket av bildene.



Konklusjon

Kanskje du har lyst til å gjeninnsette koden som skaper 20 hjul og 20 kasser med tilfeldige størrelser og posisjoner, for å se hvordan det fungerer med de endringene vi har gjort. Her er mine:

Wow, virkelig gjør det en forskjell - sammenligne det til SWF fra trinn 11

Nå har du fått punktgrafikk for å vise pent, prøve å eksperimentere med dine egne bilder i stedet! for å holde seg til det jeg har gjort. I neste del av denne serien skal vi se nærmere på dette med ulike egenskaper, og kanskje bygge en morsom liten leke ut av det!

Ikke glem at du kan stemme på hva du ønsker å lære av dette tutorial over på vår Google Moderator side. Anmeldelser



Next Page: