jogo de canhão com box2D 2.1a
É possível fazer bastante coisa com a API box2d.
Neste exemplo faremos um "carro" com um canhão em cima.
Um resumo:
O XML na variavel xmlmap está contido todos os objetos do mundo, dos 3 "mapas".
Como os objetos são criados?
Os circulos:
A função create_circles tem um for que cria os circulos um por um com a função create_circle.
A função create_circle recebe um xml e cria um circulo de acordo com os parâmetros e retorna um b2Body
Os "boxes":
A função create_boxies(desculpe o erro de ortografia) tem um for que cria as caixas um por um com a função create_box.
A função create_box recebe um xml e cria uma caixa de acordo com os parâmetros e retorna um b2Body
O carro é criado atravéz da função create_car, que faz o carro com as funções: create_circle , create_box , create_weldjoint e create_rvjoint
As "partes do carro"(b2Body e b2Joint) são gravadas no array carparts
Como o canhão atira?
Ao soltar a barra de espaço cria um circulo e grava no array projeteis.
Depois com o Math.sin e Math.cos e atravez da força calcula o impulso x e y
Depois aplica esse impulso no circulo e a força contraria no carro.
Eu tentei comentar bem o script
package {
import flash.ui.Keyboard;
import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
import flash.display.Sprite;
import Box2D.Collision.*;
import Box2D.Collision.Shapes.*;
import Box2D.Common.Math.*;
import Box2D.Dynamics.*;
import Box2D.Dynamics.Joints.*;
import flash.events.*;public class c_box2d extends Sprite {
var boxarray:Array = new Array(); // array onde estarão contidos os boxies
var circlearray:Array = new Array();//array onde estarão contidos os circulos
var left:Boolean = false;//se a seta esquerda estiver pressionada será true
var up:Boolean = false; //se a seta de cima estiver pressionada será true
var right:Boolean = false;//se a seta direita estiver pressionada será true
var down:Boolean = false;//se a seta de baixo estiver pressionada será true
var space:Boolean = false;//se a barra de espaço estiver pressionada será true
var carparts:Array = new Array() ;//array onde estarão contidos as partes do carro(joints,circles,boxies)
var force:int = 0;//inteiro com a forca do tiro do canhão
var force_a:Boolean ;// se true a barra de força almenta ,false diminui
var projeteis:Array = new Array(); //array onde estarão contidos os projeteis que serão disparados pelo canhão
public var world:b2World;//o mundo
//abaixo o xml com os mapas
var xmlmap:XML =
<xmlmap><mapa num="1">
<box id="0" width="2447" height="32" x="169" y="174" obj="1" type="0" friction2="on"friction="0.4" angle2="on" angle="-5"/>
<box id="1" width="2447" height="32" x="2604" y="196" obj="1" type="0" friction2="on"friction="0.4" angle2="on" angle="5"/>
<box id="2" width="5" height="132" x="3700" y="180" obj="1" type="0" friction2="on"friction="0.4" angle2="on" angle="5"/>
<circulo id="0" size="15" x="107"y="133" obj="1" type="1" />
<objeffect id="0" type="gravity" x="50" y="50" />
</mapa>
<mapa num="2">
<box id="0" width="488" height="32" x="-34" y="243" obj="1" type="0" friction2="on"friction="0.4" angle2="on" angle="5"/>
<box id="1" width="488" height="32" x="412" y="243" obj="1" type="0" friction2="on"friction="0.4" angle2="on" angle="-5"/>
<box id="2" width="488" height="32" x="885" y="243" obj="1" type="0" friction2="on"friction="0.4" angle2="on" angle="5"/>
<box id="3" width="488" height="32" x="1304" y="243" obj="1" type="0" friction2="on"friction="0.4" angle2="on" angle="-5"/>
<box id="4" width="488" height="32" x="1785" y="243" obj="1" type="0" friction2="on"friction="0.4" angle2="on" angle="5"/>
<box id="5" width="488" height="32" x="2232" y="243" obj="1" type="0" friction2="on"friction="0.4" angle2="on" angle="-5"/>
<box id="6" width="488" height="32" x="2710" y="243" obj="1" type="0" friction2="on"friction="0.4" angle2="on" angle="5"/>
<box id="7" width="488" height="32" x="3150" y="243" obj="1" type="0" friction2="on"friction="0.4" angle2="on" angle="-5"/>
<circulo id="0" size="15" x="107"y="133" obj="1" type="1" />
</mapa>
<mapa num="3">
<box id="0" width="488" height="32" x="-34" y="243" obj="1" type="0" friction2="on"friction="0.4" angle2="on" angle="5"/>
<box id="1" width="488" height="32" x="412" y="243" obj="1" type="0" friction2="on"friction="0.4" angle2="on" angle="-5"/>
<box id="2" width="488" height="32" x="885" y="243" obj="1" type="0" friction2="on"friction="0.4" angle2="on" angle="5"/>
<box id="3" width="488" height="32" x="1304" y="243" obj="1" type="0" friction2="on"friction="0.4" angle2="on" angle="-5"/>
<box id="4" width="488" height="32" x="1785" y="243" obj="1" type="0" friction2="on"friction="0.4" angle2="on" angle="5"/>
<box id="5" width="488" height="32" x="2232" y="243" obj="1" type="0" friction2="on"friction="0.4" angle2="on" angle="-5"/>
<box id="6" width="488" height="32" x="2710" y="243" obj="1" type="0" friction2="on"friction="0.4" angle2="on" angle="5"/>
<box id="7" width="488" height="32" x="3150" y="243" obj="1" type="0" friction2="on"friction="0.4" angle2="on" angle="-5"/>
<box id="8" width="100" height="32" x="3400" y="243" obj="1" type="0" friction2="on"friction="0.4" />
<box id="9" width="15" height="500" x="3650" y="110" obj="3" type="0" friction2="on"friction="0.025" angle2="on" angle="55" />
<box id="10" width="300" height="32" x="4000" y="-30" obj="1" type="0" friction2="on"friction="0.4" />
<circulo id="0" size="15" x="107"y="133" obj="1" type="1" />
</mapa>
</xmlmap>;
public function c_box2d() {
var grav=new b2Vec2(00,10);//b2Vec2 onde estarão contida o valor da gravidade
world=new b2World(grav,true);//cria o mundo
stage.addEventListener(Event.ENTER_FRAME,update);//enter frame
stage.addEventListener(KeyboardEvent.KEY_DOWN,kdown);
stage.addEventListener(KeyboardEvent.KEY_UP,kup);
create_boxies(1);//cria os boxies do primeiro mapa
create_circles(1);//cria os circulos do primeiro mapa
create_car(-1090 , 0);//cria o carro na posição x:3000 e y 0
//as três linhas abaixo cria o evendo para os botões de criar mapa
painel.mapa1.addEventListener(MouseEvent.CLICK, mp1);//bt mapa 1
painel.mapa2.addEventListener(MouseEvent.CLICK, mp2);//bt mapa 2
painel.mapa3.addEventListener(MouseEvent.CLICK, mp3);//bt mapa 3
}
function update(e:Event):void {
x = carparts[6].GetPosition().x * -30 + 225; //atualiza a posição do stage
y = carparts[6].GetPosition().y * -30 + 225; //atualiza a posição do stage
painel.x = (x) * -1+ 278;//atualiza a posição do mc painel
painel.y = (y) * -1+ 50;//atualiza a posição do mc painel
if(space){//verifica se a barra de espaço está precionada
if(force == 0){
force_a = true;// se force for 0 force_a vai ser true e a barra vai almentar
}
if(force == 300){
force_a = false; // se force for 300 que é o limite force_a vai ser false e vai diminuir a barra
}
if(force_a == true){
force +=10; //almenta a força
}
if(force_a == false){
force -=10; // diminui a força caso já tenha batido nos 300
}
}else{
if(force > 0){
var valorx = Math.cos(carparts[11].GetAngle()) ; // calcula o seno do angulo do canhão
var valory = Math.sin(carparts[11].GetAngle()) ;// calcula o cosseno do angulo do canhão
var fx:Number = (force/ (Math.abs(valorx) + Math.abs(valory))) * valorx / 10;// faz um pequeno calculo de proporção e calcula o impulso na posicao x
var fy:Number = (force/ (Math.abs(valorx) + Math.abs(valory))) * valory / 10;// faz um pequeno calculo de proporção e calcula o impulso na posicao y
//abaixo cria o projetil
projeteis[projeteis.length] = create_circle(<circulo size="10" x={valorx * 45 + carparts[11].GetPosition().x*30} y={valory * 45 + carparts[11].GetPosition().y*30} obj="1" type="1" density="5"/>);
//abaixo aplica o impulso ao projetil
projeteis[projeteis.length-1].ApplyImpulse(new b2Vec2(fx , fy),carparts[11].GetPosition());
//abaixo alica a força contraria ao impulso do projetil
carparts[11].ApplyImpulse(new b2Vec2(fx*-1, fy*-1),carparts[11].GetPosition());
}
force = 0 ; //zera a variavel force
}
painel.forcebar.width = force; //atualiza o tamanho da barra de acondo com a var force
if(right){
carparts[4].SetMaxMotorTorque(350);//o máximo de torque do motor
carparts[4].SetMotorSpeed(-25); // a velocidade
carparts[5].SetMaxMotorTorque(350);
carparts[5].SetMotorSpeed(-15);
}
if(left){
carparts[4].SetMaxMotorTorque(350);
carparts[4].SetMotorSpeed(25);
carparts[5].SetMaxMotorTorque(350);
carparts[5].SetMotorSpeed(15);
}
if(!left && !right){
//caso não esteja pressionado nenhuma tecla
carparts[4].SetMaxMotorTorque(0);
carparts[4].SetMotorSpeed(0);
carparts[5].SetMaxMotorTorque(0);
carparts[5].SetMotorSpeed(0);
}
if(up){
carparts[12].EnableLimit(false); // desabilita o limite
//carparts[12].EnableMotor(true);
carparts[12].SetMaxMotorTorque(10000000); // o torque do motor do canhão
carparts[12].SetMotorSpeed(-2); // a velocidade
carparts[12].SetLimits(carparts[12].GetJointAngle(), carparts[12].GetJointAngle());
}
if(down){
carparts[12].EnableLimit(false);
carparts[12].SetMaxMotorTorque(10000000);
carparts[12].SetMotorSpeed(2);
carparts[12].SetLimits(carparts[12].GetJointAngle(), carparts[12].GetJointAngle());
}
if(!up && !down){
carparts[12].EnableLimit(true); // trava o eixo do canhão de acordo com o limite setado em cima
}
// abaixo atualiza a posição e rotação dos objetos
for (var bb:b2Body = world.GetBodyList(); bb; bb = bb.GetNext()) {
if (bb.GetUserData() is Sprite) {
var sprite:Sprite=bb.GetUserData() as Sprite;
sprite.x=bb.GetPosition().x*30;//atualiza a posição x e multiplica por 30(a escala)
sprite.y=bb.GetPosition().y*30;//atualiza a posição y e multiplica por 30(a escala)
sprite.rotation = bb.GetAngle() * (180/Math.PI); // atualiza a rotação, transformando bb.GetAngle que é em radianos para graus
}
}
world.Step(1/30 , 10, 10); // atualiza o mundo
}
function kdown(e:KeyboardEvent){ //quando a tecla for pressionada
switch(e.keyCode){
case 37:
left = true;
break;
case 39:
right = true;
break;
case 38:
up = true;
break;
case 40:
down = true;
break;
case Keyboard.SPACE:
space = true;
break;
}
}
function kup(e:KeyboardEvent){ // quando a tecla for solta
switch(e.keyCode){
case 37:
left = false;
break;
case 39:
right = false;
break;
case 38:
up = false;
break;
case 40:
down = false;
break;
case Keyboard.SPACE:
space = false;
break;
}
}
function create_car(_x, _y):void {
var xx = _x; //posição do carro
var yy = _y;//posição do carro
/*quadrado esquerdo*/carparts[2] = create_box(<box width="8" height="35" x={ xx + 31} y={ yy +62} obj="4" type="2"/>);
/*quadrado direito*/carparts[3] = create_box(<box width="8" height="35" x={ xx + 178} y={ yy +62} obj="4" type="2"/>);
/*pneu esquerdo*/carparts[0] = create_circle(<circulo size="33" x={ xx + 31} y={ yy +71} obj="1" type="1" friction2="on" friction="10"/>);
/*pneu direito*/carparts[1] = create_circle(<circulo size="33" x={ xx + 178} y={ yy +71} obj="1" type="1" friction2="on" friction="0.5"/>);
/*joint do pneu esquerdo*/carparts[4] = create_rvjoint(carparts[0],carparts[2], carparts[0].GetWorldCenter());
/*joint do pneu esquerdo*/carparts[5] = create_rvjoint(carparts[1],carparts[3], carparts[1].GetWorldCenter());
/*BASE*/carparts[6] = create_box(<box width="206" height="16" x={ xx + 103} y={ yy +42} obj="1" type="2" density="10"/>);
/*joint pneu-base left*/carparts[7] = create_weldjoint(carparts[6],carparts[2], carparts[2].GetWorldCenter());
/*joint pneu-base left*/carparts[8] = create_weldjoint(carparts[6],carparts[3], carparts[3].GetWorldCenter());
/*base canhão*/carparts[9] = create_box(<box width="8.7" height="24" x={ xx + 84} y={ yy + 24.2} obj="4" type="2"/>);
/*joint base-base_canhão*/carparts[10] = create_weldjoint(carparts[6],carparts[9], carparts[9].GetWorldCenter());
/*circ_canhão*/carparts[11] = create_circle(<circulo size="21.5" x={ xx + 84.5} y={ yy + 12} obj="1" type="1"/>);
/*joint canhão*/carparts[12] = create_rvjoint(carparts[9],carparts[11], carparts[11].GetWorldCenter());
/*canhão_lado1*/carparts[13] = create_box(<box width="33.9" height="3.2" x={ xx + 109.6} y={ yy +6.7} obj="1" type="2" />);
/*canhão_lado2*/carparts[14] = create_box(<box width="33.9" height="3.2" x={ xx + 109.6} y={ yy +16.1} obj="1" type="2" />);
/*joint canhão_lado1*/carparts[15] = create_weldjoint(carparts[11],carparts[13], carparts[13].GetWorldCenter());
/*joint canhão_lado2*/carparts[16] = create_weldjoint(carparts[11],carparts[14], carparts[14].GetWorldCenter());
}
public function create_weldjoint(body1, body2, local):b2WeldJoint{ //declara uma função que retorna um b2WeldJoint
// joint fixo
var weldJointDef:b2WeldJointDef = new b2WeldJointDef(); //cria a definição do weldjointweldJointDef.Initialize(body1, body2, local); // essa função recebe 2 b2Bodys e o local onde vai ficar preso ( b2Vec2 )
var r = world.CreateJoint(weldJointDef); // esse método do world cria o joint e coloca ele no mundo. Esse método além de criar o mundo retorna um b2WeldJoint
return r; // retorna a variavel r(b2WeldJoint)
}
public function create_rvjoint(body1, body2, local,motor:Boolean = true):b2RevoluteJoint{
// joint que pode rotacionar
var revoluteJointDef:b2RevoluteJointDef = new b2RevoluteJointDef();// cria a definição
revoluteJointDef.Initialize(body1,body2 , local); // junta os dois b2Body onde local é o eixo
revoluteJointDef.enableMotor=motor; // se a variavel motor for true vai habilitar o motor
var r = world.CreateJoint(revoluteJointDef); // cria o joint de acordo com a definição
return r ; // retorna o joint
}
function create_boxies(number:Number):void {
number-=1;
for (var i = 0; i <= xmlmap.mapa[number].box.length() - 1; i++) {
boxarray[i]=create_box(xmlmap.mapa[number].box[i]);
}
}
function create_box( xml:XML):b2Body {
var xxboxShape:b2PolygonShape = new b2PolygonShape();
var body; // declara uma variavel
var xfixtureDef:b2FixtureDef = new b2FixtureDef();
var xbodyDef:b2BodyDef = new b2BodyDef();
xxboxShape = new b2PolygonShape();
xxboxShape.SetAsBox((xml.@width / 30)/2 , (xml.@height / 30) / 2 );
xfixtureDef.shape=xxboxShape;
xfixtureDef.density=2.7;
if(xml.@density > 0){
xfixtureDef.density= xml.@density ;//
}else{
}
if (xml.@friction2=="on") {
xfixtureDef.friction=xml.@friction;
} else {
xfixtureDef.friction=0.5;
}
if (xml.@restitution2=="on") {
xfixtureDef.restitution=xml.@restitution;
} else {
xfixtureDef.restitution=0.2;
}
if (xml.@obj==3) {
xbodyDef.userData = new ice();
} else if(xml.@obj==1){
xbodyDef.userData = new quadra();
}else
{
xbodyDef.userData = new quadra2();
}
xbodyDef.userData.width=xml.@width;
xbodyDef.userData.height=xml.@height;
if (xml.@angle2=="on") {
xbodyDef.angle = (xml.@angle * Math.PI) / 180 ;
xbodyDef.userData.rotation=xml.@angle;
}
xbodyDef.type=0;
if (xml.@type==2) {
xbodyDef.type=2;
}
addChildAt(xbodyDef.userData,0);
xbodyDef.position.Set(xml.@x / 30 ,xml.@y / 30);
body=world.CreateBody(xbodyDef);
body.CreateFixture(xfixtureDef);
return body;
}
function create_circle(xml:XML):b2Body{
//declara as variaveis
var xcircleShape:b2CircleShape;
var body;
var xfixtureDef:b2FixtureDef = new b2FixtureDef();
var xbodyDef:b2BodyDef = new b2BodyDef();
xcircleShape=new b2CircleShape(xml.@size/30/2); //cria a forma do circulo
xfixtureDef.shape=xcircleShape;
xfixtureDef.density=1.0;//densidade
xfixtureDef.friction=0.5;//fricção
xfixtureDef.restitution=0.2;//restituição 1 = 100%
xbodyDef.userData = new circle(); // circle() é um movieclip
xbodyDef.userData.width=xml.@size;//muda o tamanho do displayobject
xbodyDef.userData.height=xml.@size;
if (xml.@friction2=="on") {
xfixtureDef.friction=xml.@friction;
} else {
xfixtureDef.friction=0.5;
}
if (xml.@type=="1") {
xbodyDef.type=b2Body.b2_dynamicBody;// dynamicBody não é fixo
}
if(xml.@density > 0){
xfixtureDef.density= xml.@density ; //xml.@density
}else{
}
addChildAt(xbodyDef.userData,0);
xbodyDef.position.Set(xml.@x / 30 ,xml.@y / 30);
body=world.CreateBody(xbodyDef);
body.CreateFixture(xfixtureDef);
return body ;
}
function create_circles(number:Number) {
number-=1;
for (var i:Number = 0; i <= xmlmap.mapa[number].circulo.length() - 1; i++) {
circlearray[i]=create_circle(xmlmap.mapa[number].circulo[i]);
}
}
function detonatudo() {
for (var i:Number = 0; i <= boxarray.length; i++) {
removeChild(boxarray[i].GetUserData());
world.DestroyBody(boxarray[i]);
if (i==boxarray.length-1) {
i=boxarray.length;
}
}
for (i = 0; i <= circlearray.length; i++) {
removeChild(circlearray[i].GetUserData());
world.DestroyBody(circlearray[i]);
if (i==circlearray.length-1) {
i=circlearray.length;
}
}
circlearray=[];
boxarray=[];
destroy_car();
}
function destroy_car(){
for(var i:Number = 0 ; i <= 16; i++){
if(carparts[i] is b2Body){ // se carparts[i] é um b2Body vai retornar true
carparts[i].GetUserData().parent.removeChild(carparts[i].GetUserData()); // aqui remove o DisplayObject
world.DestroyBody(carparts[i]); // aqui destroi o b2Body
}
if(carparts[i] is b2Joint){ // se carparts[i] for um joint retorna true
world.DestroyJoint( carparts[i]) ;
}
}
carparts =[]; //zera o array
}
function mp1(e:MouseEvent) { // mapa 1
detonatudo();
create_circles(1);
create_boxies(1);
create_car(-1090 , 0);
}
function mp2(e:MouseEvent) {// mapa 2
detonatudo();
create_circles(2);
create_boxies(2);
create_car(50 , 0);
}
function mp3(e:MouseEvent) {// mapa 3
detonatudo();
create_circles(3);
create_boxies(3);
create_car(50 , 0);
}
}
}
Resultado:
http://megaswf.com/serve/1961944/
download:
arquivo: c_box2d.as e canhao_box2d.fla
https://rapidshare.com/files/1183835285/c.zip
arquivo: c_box2d.as e canhao_box2d.fla + o box2d (pasta source)
https://rapidshare.com/files/176347342/Source.zip
Se tiverem problemas é só postar
Discussão (1)
Carregando comentários...