Help ! At some points of bouncing..

Sep 28, 2010 at 7:18 PM

dear friends , i began to implement my arkanoid game code for farseer 3.0 with xna 4.0..everything below the code is ok, except one thing:
ball is bouncing on the bat but at some certain points of the bat the ball is not bouncing. it looses its restitution..i closely looked at that point..there are some lines inside ball..and this or these lines extend to the border of the bat.(maybe because of decomposition ?)
for example at the point of intersection of this line with border, lets assume the left side..the ball is not bouncing..but the right side is ok.
i try both earclipdecomposer and bayazit decomposer..no chance
as for the code below.. the ball is bouncing on the top side of tha bat..
but the bottom side of the bat not bouncing again at some section of the below border.(my bat is in the shape of ellipse)
i change batscale.Y = -batscale.Y  or _ana.scale.Y= -_ana.scale.Y   lines  with the parameter X then these bouncing points change ??..but i couldn't succeeded the whole border of the bat for bouncing :(
can you help me ?
pls..thx everyone.
i pictured my issue :
1st picture )  http://www.zshare.net/image/80894309ad7abb12/
2nd picture ) http://www.zshare.net/image/808944035fec71b9/
3rd picture ) http://www.zshare.net/image/80894444308fa209/
and the whole project :
http://www.zshare.net/download/8089448604161d69/
             
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Design;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Storage;
using FarseerPhysics;
using FarseerPhysics.DebugViewXNA;
using FarseerPhysics.DemoBaseXNA.DrawingSystem;
using FarseerPhysics.Controllers;
using FarseerPhysics.Collision;
using FarseerPhysics.Collision.Shapes;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Factories;
using FarseerPhysics.Common;
using FarseerPhysics.Common.Decomposition;
using FarseerPhysics.Common.ConvexHull;
using FarseerPhysics.Common.PolygonManipulation;
//using ProjectMercury;
//using ProjectMercury.Emitters;
//using ProjectMercury.Modifiers;
//using ProjectMercury.Renderers;
namespace _3
{
  /// <summary>
  /// This is the main type for your game
  /// </summary>
  public class Game1 : Microsoft.Xna.Framework.Game
  {
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    World _world = new World(new Vector2(0,-50));
    Vertices vertsbat;
    int image = 0, ts = 0;
    Vector2 batorg;
    int a;
    MouseState ms;
    Matrix Projection;
    Matrix View;
    
    List<Fixture> batfr = new List<Fixture>();
    public Vector2 batscale;
    private Fixture fr2, fr3, fr4, fr5 ;
    Texture2D tex2,bat;
    List<Vertices> batlist = new List<Vertices>();
    List<ana> textlist = new List<ana>(6);
    List<tas> taslist = new List<tas>(100);
    Random rand = new Random();
   
    DebugViewXNA debugView;
  
    const float baseScreenHeightInWorldCoordinates = 30;
   
    public Game1()
    {
      graphics = new GraphicsDeviceManager(this);
      Content.RootDirectory = "Content";
      IsFixedTimeStep = false;
    
      debugView = new DebugViewXNA(_world);
    }
    /// <summary>
    /// Allows the game to perform any initialization it needs to before starting to run.
    /// This is where it can query for any required services and load any non-graphic
    /// related content.  Calling base.Initialize will enumerate through any components
    /// and initialize them as well.
    /// </summary>
    protected override void Initialize()
    {
      // TODO: Add your initialization logic here
      
      graphics.PreferredBackBufferWidth = 1500;
      graphics.PreferredBackBufferHeight = 900;
      graphics.GraphicsDevice.PresentationParameters.MultiSampleCount = 4;
      graphics.ApplyChanges();
      base.Initialize();
    }
    protected override void LoadContent()
    {
      
      spriteBatch = new SpriteBatch(GraphicsDevice);
      DebugViewXNA.LoadContent(graphics.GraphicsDevice, Content);
      tex2 = DrawingHelper.CreateRectangleTexture(graphics.GraphicsDevice, 1500, 10, Color.YellowGreen, Color.Red); //Content.Load<texture2D>("image3");
      bat = DrawingHelper.CreateEllipseTexture(graphics.GraphicsDevice, 100, 20, Color.YellowGreen, Color.Red);//Content.Load<Texture2D>("b1");
      uint[] databat = new uint[bat.Width*bat.Height];
      bat.GetData(databat);
      vertsbat = PolygonTools.CreatePolygon(databat, bat.Width, bat.Height);
      batorg.X = vertsbat.GetCentroid().X - bat.Width/2;
      batorg.Y = vertsbat.GetCentroid().Y - bat.Height/2;
      batscale = new Vector2(1f / baseScreenHeightInWorldCoordinates,1f/baseScreenHeightInWorldCoordinates);
      
      batscale.Y = -batscale.Y;
      vertsbat.Scale(ref batscale);
      
      batlist = EarclipDecomposer.ConvexPartition(vertsbat);
      
      batfr = FixtureFactory.CreateCompoundPolygon(_world, batlist,10f) ;
      
      batfr[0].Restitution = 1f;
      batfr[0].Friction = 0f;
      
      for (int i = 0; i < 1; i++)
      {
        ana _ana = new ana();
        image += 1;
       
        _ana.kaplama = DrawingHelper.CreateCircleTexture(graphics.GraphicsDevice, 20, 1, Color.YellowGreen, Color.Red); //Content.Load<Texture2D>("a" + image);
        _ana.data = new uint[_ana.kaplama.Width * _ana.kaplama.Height];
        _ana.kaplama.GetData(_ana.data);
        _ana.verts = PolygonTools.CreatePolygon(_ana.data, _ana.kaplama.Width, _ana.kaplama.Height);
        _ana.org.X = _ana.verts.GetCentroid().X - _ana.kaplama.Width / 2;
        _ana.org.Y = _ana.verts.GetCentroid().Y - _ana.kaplama.Height / 2;
        _ana.scale = new Vector2(1f / -baseScreenHeightInWorldCoordinates, 1f / -baseScreenHeightInWorldCoordinates);
        _ana.scale.Y = -_ana.scale.Y;
        _ana.verts.Scale(ref _ana.scale);
        _ana.list = EarclipDecomposer.ConvexPartition(_ana.verts);// BayazitDecomposer.ConvexPartition(_ana.verts);
        _ana.fr = FixtureFactory.CreateCompoundPolygon(_world, _ana.list, 10f);
        _ana.fr[0].Body.BodyType = BodyType.Dynamic;
        _ana.fr[0].Body.Position = new Vector2(-2  , -1);
        _ana.anapos = _ana.fr[0].Body.Position;
        _ana.fr[0].Body.Mass = 5f;
        _ana.fr[0].Friction = 0f;
        _ana.fr[0].Restitution = 1f;
        textlist.Add(_ana);
      }
      for (int i = -2; i < 3; i++)
      {
        for (int j = -1; j < 2; j++)
        {
          ts += 1;
          tas mytas = new tas();
          mytas.tastex = Content.Load<Texture2D>("a5");
          mytas.tasorg = new Vector2(mytas.tastex.Width / 2, mytas.tastex.Height / 2);
          mytas.tasscale = new Vector2(1f / baseScreenHeightInWorldCoordinates, 1f / baseScreenHeightInWorldCoordinates);
          mytas.tasscale.Y = -mytas.tasscale.Y;
          mytas.tr[ts] = FixtureFactory.CreateRectangle(_world, mytas.tastex.Width / 30f, mytas.tastex.Height / 30f, 1);
          mytas.tr[ts].Body.Position = new Vector2(i * 5, j * 5);
          mytas.taspos = mytas.tr[ts].Body.Position;
          mytas.tr[ts].Restitution = 1f;
          mytas.tr[ts].Friction = 0f;
          taslist.Add(mytas);
        }
      }
      fr2 = FixtureFactory.CreateRectangle(_world, tex2.Width / 30f, tex2.Height / 30f, 1, new Vector2(0, -15f));
      fr3 = FixtureFactory.CreateRectangle(_world, tex2.Width / 30f, tex2.Height / 30f, 1, new Vector2(0, 15f));
      fr4 = FixtureFactory.CreateRectangle(_world, tex2.Height / 30f, tex2.Width / 30f, 1, new Vector2(-25, 0f));
      fr5 = FixtureFactory.CreateRectangle(_world, tex2.Height / 30f, tex2.Width / 30f, 1, new Vector2(25, 0f));
      fr2.Restitution = 1f; fr3.Restitution = 1f; fr4.Restitution = 1f; fr5.Restitution = 1f;
      fr2.Friction = 0f; fr3.Friction = 0f; fr4.Friction = 0f; fr5.Friction = 0f;
      JointFactory.CreateFixedAngleJoint(_world, textlist[0].fr[0].Body);
      textlist[0].fr[0].Body.IgnoreGravity = true;
   
      textlist[0].fr[0].Restitution = 1f;
 
      
      textlist[0].fr[0].Friction = 0f;
   
    
    }
    protected override void UnloadContent()
    {
      // TODO: Unload any non ContentManager content here
    }
    protected override void Update(GameTime gameTime)
    {
      
      ms = Mouse.GetState();
      
      KeyboardState s = Keyboard.GetState();
      if (s.IsKeyDown(Keys.Escape)) this.Exit();
      if (s.IsKeyDown(Keys.Space))
      {
        textlist[0].fr[0].Body.ApplyForce(new Vector2(100, 100));
      }
      _world.Step((float)(gameTime.ElapsedGameTime.Milliseconds * .001f));
      base.Update(gameTime);
    }
    protected override void Draw(GameTime gameTime)
    {
      GraphicsDevice.Clear(Color.Black);
      Viewport viewPort = GraphicsDevice.Viewport;
      Projection =
        Matrix.CreateOrthographic(baseScreenHeightInWorldCoordinates * viewPort.AspectRatio,
                                  baseScreenHeightInWorldCoordinates,
                0, 1);
    
      View = Matrix.Identity;
      Matrix transform =
            View
          * Matrix.CreateScale(viewPort.Height / baseScreenHeightInWorldCoordinates)
          * Matrix.CreateScale(1f, -1f, 1f)
          * Matrix.CreateTranslation(viewPort.Width * .5f, viewPort.Height * .5f, 0f);
      spriteBatch.Begin(SpriteSortMode.Deferred,BlendState.AlphaBlend,SamplerState.LinearClamp,DepthStencilState.None,RasterizerState.CullNone,null, transform);
      Vector2 origin2 = new Vector2(tex2.Width / 2, tex2.Height / 2);
      Vector2 scale2 = new Vector2(1f / baseScreenHeightInWorldCoordinates,
                  1f / baseScreenHeightInWorldCoordinates);
      scale2.Y = -scale2.Y;
    
      foreach (var ttt in taslist)
      {
        spriteBatch.Draw(ttt.tastex, ttt.taspos, null, Color.White, 0f, ttt.tasorg, ttt.tasscale, SpriteEffects.None, 0);
      }
      foreach (var vvv in textlist)
      {
        fr3.Restitution = 0.5f;
     
        spriteBatch.Draw(bat, batfr[0].Body.Position, null, Color.White, 0, batorg,
         batscale, SpriteEffects.None, 0);
        batfr[0].Body.Position = new Vector2(ms.X /10f, -10f);
      }
     
      spriteBatch.Draw(tex2, fr2.Body.Position, null, Color.White, 0, origin2,
        scale2, SpriteEffects.None, 0);
      spriteBatch.Draw(tex2, fr3.Body.Position, null, Color.White, 0, origin2,
          scale2, SpriteEffects.None, 0);
      spriteBatch.Draw(tex2, fr4.Body.Position, null, Color.White, MathHelper.PiOver4 * 90, origin2,
            scale2, SpriteEffects.None, 0);
      spriteBatch.Draw(tex2, fr5.Body.Position, null, Color.White, MathHelper.PiOver4 * 90, origin2,
            scale2, SpriteEffects.None, 0);
      
      spriteBatch.End();
    
      debugView.RenderDebugData(ref Projection, ref View);
     
      base.Update(gameTime);
    }
  }
}
public class ana
{
  public Vertices verts;
  public List<Vertices> toRemove = new List<Vertices>();
  public List<Fixture> fr = new List<Fixture>();
  public List<Vertices> list;
  public Texture2D kaplama;
  public Vector2 anapos;
  public Vector2 org;
  public Vector2 scale;
  public uint[] data;
}
public class tas
{
  public Fixture[] tr = new Fixture[100];
  public Texture2D tastex;
  public Vector2 taspos;
  public Vector2 tasorg;
  public Vector2 tasscale;
}



Coordinator
Sep 29, 2010 at 11:29 AM

When the ball hits a seem between two fixtures that makes up the decomposed bat, then the engine is not 100% accurate and this kind of behavior can occur. I suggest you use a shape that does not need to be decomposed (a convex shape) or decompose the polygon yourself to minimize the impact of the seems. Another option is also to create a loopshape made up of edgeshapes and test if that works better.