Box2D for Flash og AS3: Building Structure

Box2D for Flash og AS3: Building Structure
Del
Del
11
Del
Dette Cyber ​​Monday Envato Tuts + kurs vil bli redusert til bare $ 3. Ikke gå glipp av.

I de to første delene av denne serien, vi laget to enkle typer objekt, gjengitt ved hjelp av Flash visningslisten. I denne delen vil vi se hvordan å utvide dette til å la oss lage så mange forskjellige typer objekt som vi ønsker, uten vår kode får all tangled opp!


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



Trinn 1: Nye Balls Vennligst

La oss ta en rask titt på hvor vi slapp:

Bunch of hjul og kasser spretter rundt. Hjulene ikke alle har de samme egenskaper; hvert hjul har en tilfeldig størrelse, restitusjon, friksjon, og tetthet. Ditto for kassene.

Det har vært fint for testing, men nå la oss gjøre ting litt mindre tilfeldig. Vi vil starte med å bytte ut hjulene med tennisballer, som alle har de samme egenskapene.

Først tegne en tennisball (eller få et bilde av en). Her er mine:

For å gjøre din konsistent med mine, sørg for at det heter TennisBall.png, at du lagrer den i \\ lib \\, at det er 35x35px, og at den har en gjennomsiktig bakgrunn. (Du kan endre noen av disse punktene, hvis du vil, men du må finne ut hvordan du endrer koden deretter.)

Embed PNG inn Main.as fil, akkurat som vi har gjort før: product: [Embed (kilde = '.. /lib /TennisBall.png')] offentlig Var tennisball: Klasse;

Nå, lage to matriser: en for tennis ball box2D objekter, og en for tilsvarende bilder:
offentlig Var tennisBallArray: Array, offentlige Var tennisBallImages: Array; tennisBallArray = new Array (); tennisBallImages = new Array ();

(Dette er alt mye det samme som vi gjorde i den andre delen av denne serien, så ta en titt på at hvis du trenger en oppfriskning.)

Nå trenger vi en funksjon for å lage et enkelt tennisball. Her er hva vi bruker til å lage et enkelt hjul:
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 * pxToM, pxStartY * pxToM); 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 * mToPx; wheelImage.height = mRadius * 2 * mToPx; Var wheelSprite: Sprite = new Sprite (); wheelSprite.addChild (wheelImage); wheelSprite.x = pxStartX; wheelSprite.y = pxStartY; wheelImages.push (wheelSprite); this.addChild (wheelSprite); wheelSprite.addEventListener (MouseEvent.CLICK, onClickWheelImage);}

Vi kan kopiere dette og endre det til våre behov. Siden alle tennisballer vil ha de samme egenskaper (størrelse, restitusjon, friksjon, og tetthet), trenger vi ikke den mRadius argument, og vi trenger ikke å bruke tilfeldige tall overalt. Det er vanskelig å gjette hvilke verdier av restitusjon og så videre vil være riktig, så bare ha en gå - vi kan alltid rette dem senere

Her er mitt createTennisBall () -funksjonen:
privat funksjon createTennisBall (pxStartX. Antall, pxStartY: Antall, mVelocityX: Antall, mVelocityY: Number): void {var tennisBallBodyDef: b2BodyDef = new b2BodyDef (); tennisBallBodyDef.type = b2Body.b2_dynamicBody; tennisBallBodyDef.position.Set (pxStartX * pxToM, pxStartY * pxToM); Var tennisBallBody: b2Body = world.CreateBody (tennisBallBodyDef); Var circleShape: b2CircleShape = new b2CircleShape (35 * 0,5 * pxToM); Var tennisBallFixtureDef: b2FixtureDef = new b2FixtureDef (); tennisBallFixtureDef.shape = circleShape; tennisBallFixtureDef.restitution = 0,8; tennisBallFixtureDef.friction = 0,75; tennisBallFixtureDef.density = 1,0; Var tennisBallFixture: b2Fixture = tennisBallBody.CreateFixture (tennisBallFixtureDef); Var startingVelocity: b2Vec2 = new b2Vec2 (mVelocityX, mVelocityY); tennisBallBody.SetLinearVelocity (startingVelocity); tennisBallArray.push (tennisBallBody); Var tennisBallImage: Bitmap = ny tennisball (); Var tennisBallSprite: Sprite = new Sprite (); tennisBallSprite.addChild (tennisBallImage); tennisBallSprite.x = pxStartX; tennisBallSprite.y = pxStartY; tennisBallImages.push (tennisBallSprite); this.addChild (tennisBallSprite); //tennisBallSprite.addEventListener(MouseEvent.CLICK, onClickWheelImage);}

Et par ting å merke seg:

b2CircleShape () konstruktør forventer å motta radius av tennisball, i meter , og jeg ønsker ikke å squash eller forstørre bildet jeg har gjort. Jeg antar at jeg kunne slå opp radius av en faktisk tennis ball, angir denne verdien i her, og endre pxToM skaleringsfaktor for å gjøre alt annet i form, men i stedet har jeg bare fortalt konstruktøren å konvertere pixel radius av min tennis ball bilde for å meter

Restituion er bounciness av objektet, på en skala fra 0 til 1..; tennisballer er ganske bouncy så jeg har satt dette ganske høy

Friksjon er også mellom 0 og 1.; tennisballer er ganske grov så jeg satt dette ganske høyt, for

Tetthet er ikke begrenset til noen bestemt område.; tennisballer er for det meste luft, så jeg setter denne til samme verdi som mine kasser (som jeg også antar er tom).

I motsetning til i createWheel (), det er ikke nødvendig å endre størrelsen på bildet (som jeg nevnt ovenfor), så jeg har slettet disse linjene.

Jeg har bare kommentert den onClickWheelImage arrangementet lytteren ut for nå, så det er ikke relevant.

Prøv å kompilere SWF . Det skal fungere - hvis det ikke gjorde det, du savnet noe ut - men siden vi ikke er faktisk ringer createTennisBall () fra hvor som helst, ingenting vil være forskjellig



Trinn 2: Opprette tennisballer <. br>

La oss bare fjerne hjulene med en gang, og erstatte dem med tennisballer. Endre denne koden, i getStarted ():
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)}

... til dette:
for (var i: int = 0; i < 20; i ++) {createTennisBall (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)}

Legg merke til at det første argumentet er slettet, siden vi ikke manuelt angi størrelsen noe mer, men alle andre argumenter forbli den samme. Prøv selv:

Hmm ... ikke helt rett. Ah, selvfølgelig - vi ikke legge noen kode for å gjengi tennisballer. Vi vil gjøre det neste. Endre onTick () fra dette:
privat funksjon onTick (a_event: Timerevent): void {world.Step (0,025, 10, 10); world.DrawDebugData (); Var wheelImage: Sprite; for hver (var wheelBody: b2Body i wheelArray) {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); } 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); crateImage.rotation = crateBody.GetAngle () * radToDeg; }}

... til dette:
privat funksjon onTick (a_event: Timerevent): void {world.Step (0,025, 10, 10); world.DrawDebugData (); Var tennisBallImage: Sprite; for hver (var tennisBallBody: b2Body i tennisBallArray) {tennisBallImage = tennisBallImages [tennisBallArray.indexOf (tennisBallBody)]; tennisBallImage.x = (tennisBallBody.GetPosition () x * mToPx.) - (tennisBallImage.width * 0,5); tennisBallImage.y = (. tennisBallBody.GetPosition () y * mToPx) - (tennisBallImage.height * 0,5); } 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); crateImage.rotation = crateBody.GetAngle () * radToDeg; }}

(Det er egentlig bare et tilfelle av å gjøre et søk-og-erstatt, bytte "hjulet" til "tennisball".) Prøv SWF nå:

Bedre, men vi har ikke noe rotasjon (vi ikke trenger det før, fordi hjulene var alle rotasjonssymmetrisk). Legge til at nå:
Var tennisBallImage: Sprite, for hver (var tennisBallBody: b2Body i tennisBallArray) {tennisBallImage = tennisBallImages [tennisBallArray.indexOf (tennisBallBody)]; tennisBallImage.x = (tennisBallBody.GetPosition () x * mToPx.) - (tennisBallImage.width * 0,5); tennisBallImage.y = (. tennisBallBody.GetPosition () y * mToPx) - (tennisBallImage.height * 0,5); tennisBallImage.rotation = tennisBallBody.GetAngle () * radToDeg;}

Ah. Husk at vi hadde dette problemet med kassene? Husker du hvordan vi løste det? Ha en gå på å gjøre det samme her, på egen hånd. Min løsning er under hvis du ønsker å sjekke:
privat funksjon createTennisBall (pxStartX: Antall, pxStartY: Antall, mVelocityX: Antall, mVelocityY: Number): void {var tennisBallBodyDef: b2BodyDef = new b2BodyDef (); tennisBallBodyDef.type = b2Body.b2_dynamicBody; tennisBallBodyDef.position.Set (pxStartX * pxToM, pxStartY * pxToM); Var tennisBallBody: b2Body = world.CreateBody (tennisBallBodyDef); Var circleShape: b2CircleShape = new b2CircleShape (35 * 0,5 * pxToM); Var tennisBallFixtureDef: b2FixtureDef = new b2FixtureDef (); tennisBallFixtureDef.shape = circleShape; tennisBallFixtureDef.restitution = 0,8; tennisBallFixtureDef.friction = 0,75; tennisBallFixtureDef.density = 1,0; Var tennisBallFixture: b2Fixture = tennisBallBody.CreateFixture (tennisBallFixtureDef); Var startingVelocity: b2Vec2 = new b2Vec2 (mVelocityX, mVelocityY); tennisBallBody.SetLinearVelocity (startingVelocity); tennisBallArray.push (tennisBallBody); Var tennisBallImage: Bitmap = ny tennisball (); Var tennisBallSprite: Sprite = new Sprite (); tennisBallSprite.addChild (tennisBallImage); tennisBallImage.x - = tennisBallImage.width /2; tennisBallImage.y - = tennisBallImage.height /2; tennisBallSprite.x = pxStartX; tennisBallSprite.y = pxStartY; tennisBallImages.push (tennisBallSprite); this.addChild (tennisBallSprite); //tennisBallSprite.addEventListener(MouseEvent.CLICK, onClickWheelImage);} //... privat funksjon onTick (a_event: Timerevent): void {world.Step (0,025, 10, 10); world.DrawDebugData (); Var tennisBallImage: Sprite; for hver (var tennisBallBody: b2Body i tennisBallArray) {tennisBallImage = tennisBallImages [tennisBallArray.indexOf (tennisBallBody)]; tennisBallImage.x = (tennisBallBody.GetPosition () x * mToPx.); //- (tennisBallImage.width * 0,5); tennisBallImage.y = (tennisBallBody.GetPosition () y * mToPx.); //- (tennisBallImage.height * 0,5); tennisBallImage.rotation = tennisBallBody.GetAngle () * radToDeg; } 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); crateImage.rotation = crateBody.GetAngle () * radToDeg; }}

Test det ut.

Ace



Trinn 3: Lage Bowling Balls

Jeg vil gjerne legge til tre flere typer ball: en bowling ball, en basketball, og en gummiball. Som du kan se fra de ovennevnte, er det en smerte å gjøre det samme om og om igjen. Vi vil legge bowling ballen neste, og prøve å forenkle prosessen, slik at vi ikke trenger å holde gjør dette irriterende små endringer.

Her er min bowling ball image. Igjen, gjerne bruke din egen, men prøver å gjøre det 60x60px med navnet BowlingBall.png:

Embed bildet og legge de nødvendige arrays: product: [Bygg (kilde = '.. /lib /BowlingBall.png')]public Var BowlingBall: Klasse; //... offentlig Var bowlingBallArray: Array, offentlige Var bowlingBallImages: Array; //... bowlingBallArray = new Array (); bowlingBallImages = new Array (); < p> Skriv en createBowlingBall () -funksjonen:
privat funksjon createBowlingBall (pxStartX: Antall, pxStartY: Antall, mVelocityX: Antall, mVelocityY: Number): void {var bowlingBallBodyDef: b2BodyDef = new b2BodyDef (); bowlingBallBodyDef.type = b2Body.b2_dynamicBody; bowlingBallBodyDef.position.Set (pxStartX * pxToM, pxStartY * pxToM); Var bowlingBallBody: b2Body = world.CreateBody (bowlingBallBodyDef); Var circleShape: b2CircleShape = new b2CircleShape (60 * 0,5 * pxToM); Var bowlingBallFixtureDef: b2FixtureDef = new b2FixtureDef (); bowlingBallFixtureDef.shape = circleShape; bowlingBallFixtureDef.restitution = 0.0; //ikke bouncy bowlingBallFixtureDef.friction = 0.0; //veldig glatt bowlingBallFixtureDef.density = 20,0; //svært tung Var bowlingBallFixture: b2Fixture = bowlingBallBody.CreateFixture (bowlingBallFixtureDef); Var startingVelocity: b2Vec2 = new b2Vec2 (mVelocityX, mVelocityY); bowlingBallBody.SetLinearVelocity (startingVelocity); bowlingBallArray.push (bowlingBallBody); Var bowlingBallImage: Bitmap = new BowlingBall (); Var bowlingBallSprite: Sprite = new Sprite (); bowlingBallSprite.addChild (bowlingBallImage); bowlingBallImage.x - = bowlingBallImage.width /2; bowlingBallImage.y - = bowlingBallImage.height /2; bowlingBallSprite.x = pxStartX; bowlingBallSprite.y = pxStartY; bowlingBallImages.push (bowlingBallSprite); this.addChild (bowlingBallSprite); //bowlingBallSprite.addEventListener(MouseEvent.CLICK, onClickWheelImage);}

... og lage selve objektene:
for (var i: int = 0; i < 20; i ++) {createTennisBall (Math. tilfeldig () * (stage.stageWidth - 20) + 10, Math.random () * (stage.stageHeight - 20) + 10, (Math.random () * 100) - 50, 0); createBowlingBall (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)}

Puh. Ok, nå for gjengivelse. La oss ta en titt på vår gjengivelse kode så langt:
privat funksjon onTick (a_event: Timerevent): void {world.Step (0,025, 10, 10); world.DrawDebugData (); Var tennisBallImage: Sprite; for hver (var tennisBallBody: b2Body i tennisBallArray) {tennisBallImage = tennisBallImages [tennisBallArray.indexOf (tennisBallBody)]; tennisBallImage.x = (tennisBallBody.GetPosition () x * mToPx.); //- (tennisBallImage.width * 0,5); tennisBallImage.y = (tennisBallBody.GetPosition () y * mToPx.); //- (tennisBallImage.height * 0,5); tennisBallImage.rotation = tennisBallBody.GetAngle () * radToDeg; } 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); crateImage.rotation = crateBody.GetAngle () * radToDeg; }}

Legg merke noe? Takket være den endringen vi har gjort i det siste trinnet - å fikse rotasjon problem - de to uthevede delene er nesten identiske; bare bytte ut ordet "tennisball" for "kasse" i hvert enkelt tilfelle, og de er en perfekt match.

Dette tyder på at vi kunne kombinere dem i en enkelt loop, som kunne brukes til å gjengi alle stedene. På den måten ville vi ikke trenger å opprette en ny sløyfe å gjengi bowlingkuler. La oss se på dette neste



Trinn 4:. Rendering i en enkelt sløyfe

For å gjøre dette, trenger vi bare å kombinere tennisBallArray og crateArray inn i en enkelt tabell. Det er lettere hvis jeg vise deg:
privat funksjon onTick (a_event: Timerevent): void {world.Step (0,025, 10, 10); world.DrawDebugData (); Var generalB2BodyArray: Array = new Array (); generalB2BodyArray = generalB2BodyArray.concat (tennisBallArray, crateArray); Var generalImages: Array = new Array (); generalImages = generalImages.concat (tennisBallImages, crateImages); Var generalImage: Sprite; for hver (var generalBody: b2Body i generalB2BodyArray) {generalImage = generalImages [generalB2BodyArray.indexOf (generalBody)]; generalImage.x = (generalBody.GetPosition () x * mToPx.); generalImage.y = (generalBody.GetPosition () y * mToPx.); generalImage.rotation = generalBody.GetAngle () * radToDeg; }}

Se hvordan det fungerer? I linjene 6-10, skaper vi et par nye matriser: en inneholder alle tennis ball og kasse b2Body objekter, og den andre inneholder alle tennis ball og kasse Sprites. Viktigst, de inneholder dem i samme rekkefølge Anmeldelser - hvis det 17. element av generalImages [] er en tennisball, da det 17. eleemnt av generalB2BodyArray [] er den samme tennis ballens b2Body
Den for loop så gjør akkurat det samme som de to før den gjorde; det er bare måten mer generelt. Prøv selv:

bowling ballen bildene ikke flytte, men se hvor enkelt det er å legge dem til i renderer:
privat funksjon onTick (a_event: Timerevent): void {world.Step ( 0.025, 10, 10); world.DrawDebugData (); Var generalB2BodyArray: Array = new Array (); generalB2BodyArray = generalB2BodyArray.concat (tennisBallArray, crateArray, bowlingBallArray); Var generalImages: Array = new Array (); generalImages = generalImages.concat (tennisBallImages, crateImages, bowlingBallImages); Var generalImage: Sprite; for hver (var generalBody: b2Body i generalB2BodyArray) {generalImage = generalImages [generalB2BodyArray.indexOf (generalBody)]; generalImage.x = (generalBody.GetPosition () x * mToPx.); generalImage.y = (generalBody.GetPosition () y * mToPx.); generalImage.rotation = generalBody.GetAngle () * radToDeg; }}

Det er alt som trengs! Sjekk det ut:

Det begynner å kjøre litt sakte på min maskin, så jeg kommer til å redusere antall objekter 60-30:
for (var i: int = 0; i < 10; i ++) {createTennisBall (Math.random () * (stage.stageWidth - 20) + 10, Math.random () * (stage.stageHeight - 20) + 10, (Math.random () * 100) - 50, 0); createBowlingBall (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,

Det finnes 0)} mer rom for dem nå, også:



Trinn 5: Opprette basket

Basket, neste. Bildet er 75x75px og kalte Basketball.png:

Som vanlig starter ved å bygge bildet som en klasse: product: [Embed (kilde = '.. /lib /Basketball.png')] offentlig Var Basketball: Klasse;

Nå skal vi legge de to arrays for basketball b2Body gjenstander og Sprites. Unntatt ... vent. Hvorfor trenger vi en egen matrise for disse?

Vi ikke gjør det, faktisk! Ikke nå lenger. La oss kombinere alle våre b2Body gjenstander inn i en matrise, og alle våre Sprites til en annen. Endre dette:
offentlig Var crateArray: Array, offentlige Var crateImages: Array, offentlige Var tennisBallArray: Array, offentlige Var tennisBallImages: Array, offentlige Var bowlingBallArray: Array, offentlige Var bowlingBallImages: Array;

... til dette :
offentlig Var generalB2BodyArray: Array, offentlige Var generalImages: Array;

Endre dette:
wheelArray = new Array (); wheelImages = new Array (); crateArray = new Array (); crateImages = new Array (); tennisBallArray = new Array (); tennisBallImages = new Array (); bowlingBallArray = new Array (); bowlingBallImages = new Array ();

... til dette:
generalB2BodyArray = new Array (); generalImages = new Array ();

I hvert skape «Uansett» funksjon, endrer tilsvarende denne:
tennisBallArray.push (tennisBallBody);

... til dette:
generalB2BodyArray.push ( tennisBallBody); //eller .push (crateBody), eller hva

... og dette:
tennisBallImages.push (tennisBallSprite);

... til dette:
generalImages.push (tennisBallSprite); //eller .push (crateSprite), eller hva

Vi kan gjøre onClickWheelImage () gjelder for alle typer objekter veldig lett nå; bare endre dette én linje:
privat funksjon onClickWheelImage (event: MouseEvent): void {var spriteThatWasClicked: Sprite = event.target som Sprite; Var relatedBody: b2Body = wheelArray [wheelImages.indexOf (spriteThatWasClicked)]; Var centerX: Number = spriteThatWasClicked.x + (spriteThatWasClicked.width /2); Var centery: Number = spriteThatWasClicked.y + (spriteThatWasClicked.height /2); Var xDistance: Number = centerX - event.stageX; Var yDistance: Number = centery - event.stageY; Var xImpulse: Number = 60 * xDistance * pxToM; //Jeg plukket 60 fordi Var yImpulse: Number = 60 * yDistance * pxToM; //det "føltes riktig" til meg relatedBody.ApplyImpulse (ny b2Vec2 (xImpulse, yImpulse), relatedBody.GetPosition ());}

... som så:
privat funksjon onClickWheelImage (event: MouseEvent): void {var spriteThatWasClicked: Sprite = event.target som Sprite; Var relatedBody: b2Body = generalB2BodyArray [generalImages.indexOf (spriteThatWasClicked)]; Var centerX: Number = spriteThatWasClicked.x + (spriteThatWasClicked.width /2); Var centery: Number = spriteThatWasClicked.y + (spriteThatWasClicked.height /2); Var xDistance: Number = centerX - event.stageX; Var yDistance: Number = centery - event.stageY; Var xImpulse: Number = 60 * xDistance * pxToM; //Jeg plukket 60 fordi Var yImpulse: Number = 60 * yDistance * pxToM; //det "føltes riktig" til meg relatedBody.ApplyImpulse (ny b2Vec2 (xImpulse, yImpulse), relatedBody.GetPosition ());}

Til slutt, i onTick (), kan vi slette linjene uthevet nedenfor:
privat funksjon onTick (a_event: Timerevent): void {world.Step (0,025, 10, 10); world.DrawDebugData (); Var generalB2BodyArray: Array = new Array (); generalB2BodyArray = generalB2BodyArray.concat (tennisBallArray, crateArray, bowlingBallArray); Var generalImages: Array = new Array (); generalImages = generalImages.concat (tennisBallImages, crateImages, bowlingBallImages); Var generalImage: Sprite; for hver (var generalBody: b2Body i generalB2BodyArray) {generalImage = generalImages [generalB2BodyArray.indexOf (generalBody)]; generalImage.x = (generalBody.GetPosition () x * mToPx.); generalImage.y = (generalBody.GetPosition () y * mToPx.); generalImage.rotation = generalBody.GetAngle () * radToDeg; }}

Compile SWF å sikre at det fungerer:

Hvis den ikke gjør det, er det sannsynligvis på grunn av en savnet rekke et sted; bare sjekke feilmeldinger og prøv igjen.

Det tok en stund, men det gjør det mye enklere å legge til nye objekter. Vi er etter hvert å effektivisere hele prosessen

Det er en annen forenkling vi kan gjøre for disse matriser, men ...



Trinn 6:. Knytte bilder til b2Body Objects
< p> Hvorfor har vi den generalImages [] array? Det er rett og slett slik at vi kan knytte en b2Body til tilhørende bilde, og vice-versa. Men det er en bedre måte å gjøre dette

Hver b2Body har en intern "brukerdata" objekt -. Dette kan settes til en hvilken som helst objekt du liker, og kan hentes fra hvor som helst. Vi kan sette dette til å peke på b2Body objektets Sprite

Det er enkelt å gjøre.; i hvert skape «Uansett» () -funksjonen, endre tilsvarende denne linjen:
generalImages.push (tennisBallSprite);

... til tilsvarende dette:
tennisBallBody.SetUserData (tennisBallSprite); < p> Så, i onTick (), i stedet for å finne bildet fra en matrise, kan vi finne det ved hjelp av brukerdata:
privat funksjon onTick (a_event: Timerevent): void {world.Step (0,025, 10, 10 ); world.DrawDebugData (); Var generalImage: Sprite; for hver (var generalBody: b2Body i generalB2BodyArray) {generalImage = generalBody.GetUserData () som Sprite; generalImage.x = (generalBody.GetPosition () x * mToPx.); generalImage.y = (generalBody.GetPosition () y * mToPx.); generalImage.rotation = generalBody.GetAngle () * radToDeg; }}

(Hvis du vil, kan du erstatte brukerdata med en sprite ark og bruke blitting å gjengi objekter her. Det er ganske enkelt å gjøre det, med denne strukturen.)

Du kan faktisk fjerne generalImages [] rekke helt nå ... bortsett fra én ting:. det er fortsatt brukes i onClickWheelImage () for å få en referanse fra
bildet til b2Body

Vi kunne bare kommentere onClickWheelImage () ut, fordi vi ikke bruker det akkurat nå, men det ville være lat. Og dette reiser et godt poeng, likevel: vi må være i stand til å finne et bilde er knyttet b2Body. Dessverre, vi bruker Sprite klasse, og det har ikke en innebygd "brukerdata." - Men vi kunne gi den en

Opprett en ny klasse, kalt B2Sprite, strekker Sprite, i din \\ src \\ mappe:
pakke {import flash.display.Sprite; public class B2Sprite strekker Sprite {offentlig funksjon B2Sprite () {}}}

(jeg har brukt en kapital B for å skille den fra de offisielle Box2D klasser.)

Lag en b2Body eiendom:
pakke {import Box2D.Dynamics.b2Body; import flash.display.Sprite; public class B2Sprite strekker Sprite {public Var kroppen: b2Body; offentlig funksjon B2Sprite () {}}}

Fordi dette strekker Sprite, vil det handle akkurat det samme som en Sprite, bortsett fra med den ekstra eiendom som vi trenger.

Nå, i hvert skape «Uansett »() -funksjonen, endre tilsvarer denne koden:
Var tennisBallSprite: Sprite = new Sprite ();

... til dette:
Var tennisBallSprite: B2Sprite = new B2Sprite ();

også, uansett hvor du har tilsvarende på denne linjen:
tennisBallBody.SetUserData (tennisBallSprite);

... legge en annen linje under den, for å opprette en forbindelse fra B2Sprite til b2Body:
tennisBallBody.SetUserData (tennisBallSprite); tennisBallSprite.body = tennisBallBody;

Deretter kan du endre onClickWheelImage (), som så:
privat funksjon onClickWheelImage (event: MouseEvent): void {if (event.target er B2Sprite) {var spriteThatWasClicked : B2Sprite = event.target som B2Sprite; Var relatedBody: b2Body = spriteThatWasClicked.body; Var centerX: Number = spriteThatWasClicked.x + (spriteThatWasClicked.width /2); Var centery: Number = spriteThatWasClicked.y + (spriteThatWasClicked.height /2); Var xDistance: Number = centerX - event.stageX; Var yDistance: Number = centery - event.stageY; Var xImpulse: Number = 60 * xDistance * pxToM; //Jeg plukket 60 fordi Var yImpulse: Number = 60 * yDistance * pxToM; //det "føltes riktig" til meg relatedBody.ApplyImpulse (ny b2Vec2 (xImpulse, yImpulse), relatedBody.GetPosition ()); }}

Nå som du har gjort alt dette, kan du uncomment ut linjene som legger hendelsen lyttere for onClickWheelImage () (i tennis ball og bowling ball funksjoner for oppretting), og prøve ut SWF:

Klikk på en tennisball eller bowling ball for å se effekten.

Gi nytt navn til onClickWheelImage () -funksjonen til onClickClickableImage (). Hvis du vil, kan du prøve å lage kassene klikkbare, også



Trinn 7: Opprette Basket (Still)

Hei, ble ikke vi legge basketballer? La oss komme tilbake til det.

Så har vi fjernet bildet array, noe som betyr at vi var i ferd med å skrive den createBasketball () -funksjonen. Men, vent ... Jeg kan ikke hjelpe, men lurer på om vi trenger generalB2BodyArray [].

Det viser seg at vi ikke gjør det. Den b2world inneholder en liste over alle b2Body gjenstander inni den, så matrisen er unødvendig. Vi skal bare gjøre en rask Anmeldelser endring - jeg lover -. Og så kan vi legge til basketball

Denne listen er ikke en matrise. Det fungerer slik:.


    Du ber world.GetBodyList (), og dette gir deg den første b2Body objekt i listen

    Med denne kroppen, kaller du .GetNext () å hente neste b2Body objekt i listen.

    Hvis .GetNext () returnerer null, du har nådd slutten av listen.

    Ha en gå på omskrivninger den onTick () gjengivelse kode for å bruke denne listen i stedet for generalB2BodyArray []. Her er min løsning hvis du ønsker å sjekke:
    privat funksjon onTick (a_event: Timerevent): void {world.Step (0,025, 10, 10); world.DrawDebugData (); Var currentBody: b2Body = world.GetBodyList (); Var currentImage: B2Sprite; while (! currentBody = null) {if (currentBody.GetUserData () er B2Sprite) //viktig, siden grensene ikke har tilknyttede bilder {currentImage = currentBody.GetUserData () som B2Sprite; currentImage.x = (currentBody.GetPosition () x * mToPx.); currentImage.y = (currentBody.GetPosition () y * mToPx.); currentImage.rotation = currentBody.GetAngle () * radToDeg; } CurrentBody = currentBody.GetNext (); }}

    (jeg har benyttet anledningen til å legge til noen ekstra kontroller og endre navnet på noen variabler;. du trenger ikke å gjøre dette, men det er trolig lettere hvis du gjør det, for å holde vår kode konsekvent)

    Du kan nå fjerne alle referanser til generalB2BodyArray []. Sørg for at du teste din SWF å sjekke det fortsatt går greit:

    Opprette at basketball er nå ganske enkel. Først skriver createBasketball ():
    privat funksjon createBasketball (pxStartX: Antall, pxStartY: Antall, mVelocityX: Antall, mVelocityY: Number): void {var basketballBodyDef: b2BodyDef = new b2BodyDef (); basketballBodyDef.type = b2Body.b2_dynamicBody; basketballBodyDef.position.Set (pxStartX * pxToM, pxStartY * pxToM); Var basketballBody: b2Body = world.CreateBody (basketballBodyDef); Var circleShape: b2CircleShape = new b2CircleShape (75 * 0,5 * pxToM); Var basketballFixtureDef: b2FixtureDef = new b2FixtureDef (); basketballFixtureDef.shape = circleShape; basketballFixtureDef.restitution = 0,6; //ganske bouncy basketballFixtureDef.friction = 0,4; //litt røff basketballFixtureDef.density = 2,5; //ganske lett Var basketballFixture: b2Fixture = basketballBody.CreateFixture (basketballFixtureDef); Var startingVelocity: b2Vec2 = new b2Vec2 (mVelocityX, mVelocityY); basketballBody.SetLinearVelocity (startingVelocity); Var basketballImage: Bitmap = new Basketball (); Var basketballSprite: B2Sprite = new B2Sprite (); basketballSprite.addChild (basketballImage); basketballImage.x - = basketballImage.width /2; basketballImage.y - = basketballImage.height /2; basketballSprite.x = pxStartX; basketballSprite.y = pxStartY; basketballBody.SetUserData (basketballSprite); this.addChild (basketballSprite); basketballSprite.body = basketballBody; basketballSprite.addEventListener (MouseEvent.CLICK, onClickClickableImage);}

    ... da, lage en hel haug av dem:
    for (var i: int = 0; i < 10; i ++) {createTennisBall (Math .random () * (stage.stageWidth - 20) + 10, Math.random () * (stage.stageHeight - 20) + 10, (Math.random () * 100) - 50, 0); createBowlingBall (Math.random () * (stage.stageWidth - 20) + 10, Math.random () * (stage.stageHeight - 20) + 10, (Math.random () * 100) - 50, 0);