2 ডি প্ল্যাটফর্মার এএবিবি সংঘর্ষের সমস্যা


51

http://dl.dropbox.com/u/3724424/Programming/Gifs/game6.gif

আমার এএবিবি সংঘর্ষের রেজোলিউশনে সমস্যা আছে।


আমি প্রথমে এক্স অক্ষটি সমাধান করে, তারপরে Y অক্ষটি সমাধান করে AABB ছেদটি সমাধান করি resolve এই বাগটি প্রতিরোধ করার জন্য এটি করা হয়: http://i.stack.imgur.com/NLg4j.png


বর্তমান বিষয়টি ঠিকঠাকভাবে কাজ করে যখন কোনও বস্তু প্লেয়ারে চলে আসে এবং প্লেয়ারটিকে অনুভূমিকভাবে ঠেলে দিতে হয়। আপনি যেমন। জিআইএফ-তে দেখতে পাচ্ছেন, অনুভূমিক স্পাইকগুলি প্লেয়ারটিকে সঠিকভাবে ঠেলা দেয়।


উল্লম্ব স্পাইকগুলি যখন প্লেয়ারে চলে যায় তবে এক্স অক্ষটি এখনও প্রথমে সমাধান করা হয়। এটি "লিফট হিসাবে স্পাইকগুলি ব্যবহার করা" অসম্ভব করে তোলে।

খেলোয়াড় যখন উল্লম্ব স্পাইকগুলিতে চলে যায় (মাধ্যাকর্ষণ দ্বারা প্রভাবিত হয়, সেগুলির মধ্যে পড়ে) তখন তিনি Y অক্ষের উপরে ঠেলাঠেলি করে, কারণ X অক্ষের সাথে শুরু করার জন্য কোনও ওভারল্যাপ ছিল না।


আমি যা কিছু চেষ্টা করেছি তা হল এই লিঙ্কটির প্রথম উত্তরে বর্ণিত পদ্ধতি: 2 ডি আয়তক্ষেত্রাকার বস্তুর সংঘর্ষ সনাক্তকরণ

তবে স্পাইকস এবং চলন্ত বস্তুগুলি তাদের অবস্থান পরিবর্তন করে, গতিবেগের পরিবর্তে নাড়াচাড়া করে এবং তাদের আপডেট () পদ্ধতিটি না বলা পর্যন্ত আমি তাদের পরবর্তী ভবিষ্যদ্বাণীযুক্ত অবস্থান গণনা করি না। বলা বাহুল্য এই সমাধানটিও কার্যকর হয়নি। :(


উপরের বর্ণিত দুটি মামলাই যেমন কাজ করেছে তেমনভাবে আমাকে এএবিবি সংঘর্ষের সমাধান করতে হবে solve

এটি আমার বর্তমান সংঘর্ষের উত্স কোড: http://pastebin.com/MiCi3nA1

কেউ যদি এটি সন্ধান করতে পারে তবে আমি সত্যিই কৃতজ্ঞ হব, যেহেতু এই বাগটি শুরু থেকেই ইঞ্জিনে উপস্থিত ছিল, এবং কোনও সাফল্য ছাড়াই আমি একটি ভাল সমাধানের জন্য লড়াই করে যাচ্ছি। এটি আমাকে গুরুতরভাবে সংঘর্ষের কোডটি দেখার জন্য রাত কাটাচ্ছে এবং আমাকে "মজাদার অংশে" যেতে এবং গেমটির যুক্তি কোডিং করতে বাধা দিচ্ছে :(


আমি এক্সএনএ অ্যাপহব প্ল্যাটফর্মার ডেমো (একইসাথে বেশিরভাগ স্ট্যাটাসের অনুলিপি-পেস্ট করে) একই সংঘর্ষের সিস্টেমটি প্রয়োগ করার চেষ্টা করেছি। তবে "গেমিং" বাগটি আমার গেমটিতে ঘটে, যদিও এটি অ্যাপহব ডেমোতে ঘটে না। [জাম্পিং বাগ: http://i.stack.imgur.com/NLg4j.png ]

লাফানোর জন্য আমি প্লেয়ারটি "অনগ্রাউন্ড" কিনা তা পরীক্ষা করে দেখুন, তারপরে ভেলোসিটি.ওয়াই-তে যুক্ত করুন।

যেহেতু প্লেয়ারটির वेग.এটি.এটি Velocity.Y এর চেয়ে বেশি।

আমি বিশ্বাস করি এটি অ্যাপহাব ডেমোতে ঘটে না কারণ প্লেয়ারের বেগ। এক্স কখনও ভোলসিটি-ওয়াইয়ের চেয়ে বেশি হবে না তবে আমার ভুল হতে পারে।

আমি প্রথমে এক্স অক্ষের উপর সমাধান করে এরপরে Y অক্ষের সাহায্যে সমাধান করেছি। কিন্তু যে স্পাইকগুলির সাথে সংঘর্ষের বিষয়টি আমি উপরে উল্লেখ করেছি।


5
আসলে কিছুই ভুল হচ্ছে না। যে পদ্ধতিটি আমি ধাক্কা ব্যবহার করছি তা প্রথমে এক্স অক্ষের উপরে, তারপরে Y অক্ষের উপরে। এই কারণেই খেলোয়াড় উল্লম্ব স্পাইকগুলিতে এমনকি অনুভূমিকভাবে ঠেলাঠেলি করে। আমাকে এমন একটি সমাধান খুঁজে বের করতে হবে যা "জাম্পিং সমস্যা" এড়ায় এবং খেলোয়াড়টিকে অগভীর অক্ষের (কমপক্ষে অনুপ্রবেশ সহ অক্ষ) উপর চাপ দেয় তবে আমি এর সন্ধান পাই না।
ভিটোরিও রোমিও

1
প্লেয়ারটি যে বাধা স্পর্শ করছে তার মুখটি আপনি সনাক্ত করতে পারেন এবং
এটির

4
@ জোনাথন হবস, প্রশ্নটি পড়ুন। ভী তার কোডটি কী করছে ঠিক তা জানে, তবে কোনও নির্দিষ্ট সমস্যা কীভাবে সমাধান করা যায় তা জানে না। কোডের মাধ্যমে পদক্ষেপ নেওয়া এই পরিস্থিতিতে তাকে সহায়তা করবে না।
অ্যাটাকিংহোব

4
@ মাইক @ জোনাথন: প্রোগ্রামটির সাথে কিছুতেই "ভুল হচ্ছে না" - তিনি বুঝতে পারেন যে ঠিক কোথায় এবং কেন তার অ্যালগরিদম যা করতে চায় তা করে না। তিনি কীভাবে চান তা করতে কীভাবে অ্যালগরিদম পরিবর্তন করবেন তা জানেন না। সুতরাং এই ক্ষেত্রে ডিবাগারটি কার্যকর নয়।
ব্লুরাজা - ড্যানি পিফ্লুঘুফুট

1
@ অ্যাটাকিংহোব @ ব্লুরাজা আমি সম্মত এবং আমি আমার মন্তব্য মুছে ফেলেছি। এটাই আমি যা করছিলাম সে সম্পর্কে সিদ্ধান্তে ঝাঁপিয়ে পড়েছিলাম। আপনাকে এটি ব্যাখ্যা করতে এবং কমপক্ষে একজনকে বিপথগামী করার জন্য আমি সত্যিই ক্ষমা চাই। সত্যিই, পরের বার আমার কোনও প্রতিক্রিয়া ছাড়ার আগে আপনি সত্যিই সঠিকভাবে প্রশ্নটি শুষে নিতে আমার উপর নির্ভর করতে পারেন।
ডপপেলগ্রিনিয়ার

উত্তর:


9

ঠিক আছে, আমি বুঝতে পেরেছিলাম কেন এক্সএনএ অ্যাপহব প্ল্যাটফর্মার ডেমোতে "জাম্পিং" বাগ নেই: ডেমো সংঘর্ষের টাইলগুলি উপর থেকে নীচে পরীক্ষা করে । যখন কোনও "প্রাচীর" বিরুদ্ধে থাকে তখন প্লেয়ার একাধিক টাইল ওভারল্যাপ করে। রেজোলিউশন অর্ডারটি গুরুত্বপূর্ণ কারণ একটি সংঘর্ষের সমাধানের ফলে অন্যান্য সংঘর্ষের সমাধানও হতে পারে (তবে অন্যদিকে)। onGroundপ্লেয়ারকে ওয়াই-অ্যাক্সেসের উপরে চাপ দিয়ে সংঘর্ষের সমাধান হওয়ার পরে সম্পত্তিটি সেট করা থাকে। পূর্ববর্তী রেজোলিউশনগুলি খেলোয়াড়কে নিচে এবং / অথবা অনুভূমিকভাবে চাপ দিলে এই রেজোলিউশনটি ঘটবে না।

আমি এই লাইনটি পরিবর্তন করে এক্সএনএ ডেমোতে "জাম্পিং" বাগটি পুনরুত্পাদন করতে সক্ষম হয়েছি:

for (int y = topTile; y <= bottomTile; ++y)

এটি:

for (int y = bottomTile; y >= topTile; --y)

(আমি পদার্থবিজ্ঞানের সাথে সম্পর্কিত কিছু ধ্রুবককে টুইটও করেছি, তবে এটির বিষয়টি বিবেচনা করা উচিত নয়।)

bodiesToCheckআপনার গেমের সংঘর্ষগুলি সমাধান করার আগে সম্ভবত ওয়াই-অক্ষে বাছাই করা "জাম্পিং" বাগটি ঠিক করবে। এক্সএনএ ডেমো এবং ট্র্যাভোরের পরামর্শ অনুসারে অনুপ্রবেশের "অগভীর" অক্ষের সাথে সংঘর্ষের সমাধান করার পরামর্শ দিচ্ছি । এছাড়াও লক্ষ করুন যে এক্সএনএ ডেমো প্লেয়ারটি সংঘর্ষে সক্ষম টাইলগুলির চেয়ে দ্বিগুণ লম্বা, একাধিক সংঘর্ষের কেসটিকে আরও সম্ভাবনা তৈরি করে।


এটি আকর্ষণীয় শোনায় ... আপনি কি ভাবেন যে সংঘর্ষগুলি সনাক্ত করার আগে ওয়াই কোঅর্ডিন্টের মাধ্যমে সমস্ত কিছু অর্ডার করা আমার সমস্ত সমস্যার সমাধান করতে পারে? কোন ধরা আছে?
ভিটোরিও রোমিও

Aaaand আমি "ধরা" পেয়েছি। এই পদ্ধতিটি ব্যবহার করে, জাম্পিং বাগটি সংশোধন করা হয়েছে, তবে যদি আমি সিলিংটি আঘাতের পরে वेगটি.ওয়াই 0 তে সেট করি তবে এটি আবার ঘটে।
ভিটোরিও রোমিও

@ দেখুন: Position = nextPositionঅবিলম্বে forলুপের ভিতরে সেট করুন , অন্যথায় অযাচিত সংঘর্ষের রেজোলিউশন (সেটিং onGround) এখনও ঘটে। সিলিংটি আঘাত করার সময় প্লেয়ারটিকে উলম্বভাবে নীচে (এবং কখনই আপ) ঠেলা onGroundউচিত নয় thus এক্সএনএ ডেমো এটি এটি করে এবং আমি সেখানে "সিলিং" বাগটি ত্রুটিযুক্ত করতে পারি না।
লেফটিয়াম

পেস্টবিন .com/ টিএলআরকিউপিউবিউ - এটি আমার কোড: আমি "পজিশন" ভেরিয়েবলটি ব্যবহার না করেই পজিশনে নিজেই কাজ করি। এটি এক্সএনএ ডেমো-তে যেমন কাজ করবে ততক্ষণ যদি আমি লাইনটি বেঁধে রাখি তবে ওয়াইলোসিটি নির্ধারণ করে Y যদি আমি এটি সরিয়ে ফেলি, সিলিংয়ে লাফিয়ে যাওয়ার সময় প্লেয়ারটি ভাসতে থাকে। এটি কি স্থির করা যায়?
ভিটোরিও রোমিও

@ দেখুন: আপনার কোডটি কীভাবে onGroundসেট করা আছে তা দেখায় না , সুতরাং কেন লাফ দেওয়া ভুলভাবে অনুমোদিত investigate এক্সএনএ ডেমো এর isOnGroundঅভ্যন্তরীণ সম্পত্তি আপডেট করে HandleCollisions()। এছাড়াও, Velocity.Y0 এ সেট করার পরে , কেন মাধ্যাকর্ষণ আবার প্লেয়ারটিকে নীচে নামানো শুরু করে না? আমার অনুমান onGroundসম্পত্তিটি যথাযথভাবে সেট করা আছে। কীভাবে এক্সএনএ ডেমো আপডেট হয় previousBottomএবং isOnGround( IsOnGround) দেখুন।
লেফটিয়াম

9

আপনার পক্ষে সবচেয়ে সহজ সমাধান হ'ল যে কোনও সংঘর্ষের সমাধানের আগে বিশ্বের প্রতিটি বস্তুর বিরুদ্ধে উভয় সংঘর্ষের দিকনির্দেশ পরীক্ষা করা এবং কেবলমাত্র দুটি ফলাফল "যৌগিক সংঘর্ষ" এর মধ্যে ছোট সমাধান করুন। এর অর্থ হ'ল আপনি সর্বদা সর্বনিম্ন x কে সমাধান করার পরিবর্তে, বা সর্বদা প্রথমে y কে সমাধান করার পরিবর্তে, সবচেয়ে কম পরিমাণে সমাধান করুন।

আপনার কোডটি এরকম কিছু দেখাচ্ছে:

// This loop repeats, until our object has been fully pushed outside of all
// collision objects
while ( StillCollidingWithSomething(object) )
{
  float xDistanceToResolve = XDistanceToMoveToResolveCollisions( object );
  float yDistanceToResolve = YDistanceToMoveToResolveCollisions( object );
  bool xIsColliding = (xDistanceToResolve != 0.f);

  // if we aren't colliding on x (not possible for normal solid collision 
  // shapes, but can happen for unidirectional collision objects, such as 
  // platforms which can be jumped up through, but support the player from 
  // above), or if a correction along y would simply require a smaller move 
  // than one along x, then resolve our collision by moving along y.

  if ( !xIsColliding || fabs( yDistanceToResolve ) < fabs( xDistanceToResolve ) )
  {
    object->Move( 0.f, yDistanceToResolve );
  }
  else // otherwise, resolve the collision by moving along x
  {
    object->Move( xDistanceToResolve, 0.f );
  }
}

বড় সংশোধন : অন্যান্য উত্তরের ভাষ্য পড়া থেকে, আমি মনে করি অবশেষে আমি একটি অস্তিত অনুমান লক্ষ্য করেছি, যা এই পদ্ধতির কাজ না করার কারণ করবে (এবং এটি ব্যাখ্যা করে যে আমি কেন কিছু বুঝতে পারি না - তবে সব নয় - লোকেরা এই পদ্ধতির সাথে দেখে)। বিস্তারিতভাবে বলতে গেলে, এখানে আরও কিছু সিউডোকোড দেওয়া হয়েছে, যা আমি আগে উল্লিখিত ফাংশনগুলি বাস্তবে করছিল তা আরও স্পষ্টভাবে প্রদর্শন করছে:

bool StillCollidingWithSomething( MovingObject object )
{
  // loop over every collision object in the world.  (Implementation detail:
  // don't test 'object' against itself!)
  for( int i = 0; i < collisionObjectCount; i++ )
  {
    // if the moving object overlaps any collision object in the world, then
    // it's colliding
    if ( Overlaps( collisionObject[i], object ) )
      return true;
  }
  return false;
}

float XDistanceToMoveToResolveCollisions( MovingObject object )
{
  // check how far we'd have to move left or right to stop colliding with anything
  // return whichever move is smaller
  float moveOutLeft = FindDistanceToEmptySpaceAlongNegativeX(object->GetPosition());
  float moveOutRight = FindDistanceToEmptySpaceAlongX(object->GetPosition());
  float bestMoveOut = min( fabs(moveOutLeft), fabs(moveOutRight) );

  return minimumMove;
}

float FindDistanceToEmptySpaceAlongX( Vector2D position )
{
  Vector2D cursor = position;
  bool colliding = true;
  // until we stop colliding...
  while ( colliding )
  {
    colliding = false;
    // loop over all collision objects...
    for( int i = 0; i < collisionObjectCount; i++ )
    {
      // and if we hit an object...
      if ( Overlaps( collisionObject[i], cursor ) )
      {
        // move outside of the object, and repeat.
        cursor.x = collisionObject[i].rightSide;
        colliding = true;

        // break back to the 'while' loop, to re-test collisions with
        // our new cursor position
        break;
      }
    }
  }
  // return how far we had to move, to reach empty space
  return cursor.x - position.x;  
}

এটি "প্রতি বস্তু জোড়া" পরীক্ষা নয়; এটি পৃথক পৃথকভাবে বিশ্বের মানচিত্রের প্রতিটি টাইলের বিরুদ্ধে চলমান বস্তুর পরীক্ষা ও সমাধানের মাধ্যমে কাজ করে না (এ পদ্ধতিটি কখনই নির্ভরযোগ্যভাবে কাজ করবে না এবং টাইলের আকার হ্রাস হওয়ায় ক্রমবর্ধমান বিপর্যয়কর পথে ব্যর্থ হবে)। পরিবর্তে, এটি একই সাথে বিশ্বের মানচিত্রের প্রতিটি বস্তুর বিরুদ্ধে চলন্ত বস্তুটি পরীক্ষা করছে এবং তারপরে পুরো বিশ্বের মানচিত্রের বিরুদ্ধে সংঘর্ষের ভিত্তিতে সমাধান করছে।

এটিই আপনি নিশ্চিত করেন যে (প্রাচুর্য) প্রাচীরের অভ্যন্তরে পৃথক প্রাচীর টাইলগুলি কখনও সংলগ্ন টাইলগুলির মধ্যে খেলোয়াড়কে উপরে এবং নিচে নামায় না, ফলস্বরূপ প্লেয়ারটি তাদের মধ্যে কিছু অ-অরক্ষিত জায়গায় আটকে যায়; সংঘর্ষের সমাধানের দূরত্বগুলি সর্বদা বিশ্বে খালি জায়গার সমস্ত উপায়ে গণনা করা হয়, কেবলমাত্র একটি একক টাইলের সীমানায় নয় যা এর উপরে আরও একটি শক্ত টালি থাকতে পারে।


1
i.stack.imgur.com/NLg4j.png - আমি যদি উপরের পদ্ধতিটি ব্যবহার করি তবে এটি ঘটে।
ভিটোরিও রোমিও

1
হতে পারে আমি আপনার কোডটি সঠিকভাবে আন্ডারট্রেড করছি না, তবে চিত্রটির সমস্যাটি আমাকে বোঝাতে দাও: যেহেতু প্লেয়ারটি X অক্ষের উপর দ্রুত, তাই এক্স অনুপ্রবেশটি Y অনুপ্রবেশের চেয়ে বেশি is সংঘর্ষ ওয়াই অক্ষটি চয়ন করে (কারণ অনুপ্রবেশ ছোট) এবং খেলোয়াড়টিকে উল্লম্বভাবে ঠেলে দেয়। প্লেয়ারটি যথেষ্ট ধীর গতিতে এটি ঘটে না যাতে এক্স অনুপ্রবেশের চেয়ে Y অনুপ্রবেশ সর্বদা> থাকে।
ভিটোরিও রোমিও

1
@ দেখুন এই চিত্রটি ব্যবহার করে কোনও ভুল আচরণ হিসাবে আপনি এখানে চিত্রটির কোন ফলকে উল্লেখ করছেন? আমি ফলক 5 ধরে নিচ্ছি, যার মধ্যে খেলোয়াড় স্পষ্টতই Y এর চেয়ে এক্স এর চেয়ে কম অনুপ্রবেশ করছে, যার ফলশ্রুতি এক্স অক্ষের সাথে ধাক্কা দেওয়া হবে - যা সঠিক আচরণ। আপনি কেবল তখনই খারাপ আচরণ পাবেন যখন আপনি বেগের উপর ভিত্তি করে (আপনার চিত্রের মতো) রেজোলিউশনের জন্য অক্ষ বেছে নিচ্ছেন, এবং প্রকৃত অনুপ্রবেশের ভিত্তিতে নয় (যেমন আমি বলেছি)।
ট্রেভর পাওয়েল

1
@ ট্রেভর: আহ, আমি যা বলছি তা দেখছি। if(fabs( yDistanceToResolve ) < fabs( xDistanceToResolve ) || xDistanceToResolve == 0) { object->Move( 0.f, yDistanceToResolve ); } else { object->Move( xDistanceToResolve, 0.f ); }
সেক্ষেত্রে

1
ব্লুরাজ রাজা আপনার পরামর্শ অনুসারে আমি কম শর্তসাপেক্ষে আমার উত্তর সম্পাদনা করেছি। ধন্যবাদ!
ট্রেভর পাওয়েল

6

সম্পাদন করা

আমি এটি উন্নত করেছি

মনে হচ্ছে যে মূল জিনিসটি আমি পরিবর্তন করেছি তা ছেদগুলিকে শ্রেণিবদ্ধ করা।

ছেদগুলি হয়:

  • সিলিং বাম্প
  • গ্রাউন্ড হিট (মেঝে থেকে ধাক্কা)
  • মাঝ বায়ু প্রাচীর সংঘর্ষ
  • গ্রাউন্ডেড প্রাচীরের সংঘর্ষ

এবং আমি তাদের সেভাবে সমাধান করি

খেলোয়াড় টাইলের কমপক্ষে 1/4 উপায় হিসাবে স্থল সংঘর্ষের সংজ্ঞা দিন

সুতরাং এটি একটি স্থল সংঘর্ষ এবং প্লেয়ার ( নীল ) টাইলের উপরে বসে থাকবে ( কালো ) স্থল সংঘর্ষ

তবে এটি কোনও স্থল সংঘর্ষ নয় এবং খেলোয়াড় টাইলের ডানদিকে "স্লিপ" করবেন একটি গ্রাউন্ড সংঘর্ষের খেলোয়াড় হতে হবে না gonig দ্বারা পিছলে যাবে

এই পদ্ধতিতে প্লেয়ার আর দেয়ালের পাশে ধরা পড়বে না


আমি আপনার পদ্ধতিটি চেষ্টা করেছি (আমার বাস্তবায়ন দেখুন: পেস্টবিন. com/ হার্নএনএনপি) তবে আমি কোথায় জানি না প্লেয়ারের বেগটি 0 তে সেট করতে হবে তবে এনক্রি <= 0 থাকলে আমি এটিকে 0 এ সেট করার চেষ্টা করেছি তবে এটি প্লেয়ারকে মাঝ বায়ুতে থামতে দেয় প্রাচীরের সাথে স্লাইডিংয়ের সময় এবং তাকে বারবার দেয়াল-জাম্প করতে দেয়।
ভিটোরিও রোমিও

যাইহোক, প্লেয়ার স্পাইকের সাথে ইন্টারঅ্যাক্ট করার সময় এটি সঠিকভাবে কাজ করে (যেমন .gif-এ দেখানো হয়েছে)। আপনি যদি দেয়াল-জাম্পিং (এছাড়াও দেয়ালে আটকে যাওয়া) সমস্যার সমাধান করতে আমাকে সহায়তা করতে পারেন তবে আমি সত্যিই প্রশংসা করব। মনে রাখবেন যে আমার দেয়ালগুলি বেশ কয়েকটি এএবিবি টাইলস দিয়ে তৈরি।
ভিটোরিও রোমিও

অন্য একটি মন্তব্য পোস্ট করার জন্য দুঃখিত, তবে একটি নতুন প্রকল্পে আপনার কোডটি অনুলিপি-পেস্ট করার পরে, এসপকে 5 এ পরিবর্তন করে এবং টাইলগুলি দেওয়ালের আকারে বানানোর পরে, জাম্পিং বাগটি ঘটে (এই চিত্রটি দেখুন: i.stack.imgur.com /NLg4j.png)
ভিটোরিও রোমিও

ঠিক আছে, এখনই চেষ্টা করে দেখুন।
বোবোবোবো

কোড নমুনাটির জন্য +1 (অনুভূমিকভাবে "স্পাইক" ব্লকগুলি
অনুভূত করে

3

পূর্বে নোট:
আমার ইঞ্জিনটি একটি সংঘর্ষ সনাক্তকরণ শ্রেণি ব্যবহার করে যা সমস্ত বস্তুর সাথে রিয়েল টাইমের সংঘর্ষগুলি পরীক্ষা করে কেবল তখনই যখন কোনও বস্তু সরে যায় এবং কেবল গ্রিড স্কোয়ারগুলিতে বর্তমানে এটি দখল করে।

আমার সমাধান:

আমি যখন আমার 2 ডি প্ল্যাটফর্মারে এই জাতীয় সমস্যার বিরুদ্ধে দৌড়েছি তখন আমি নীচের মতো কিছু করেছি:

- (ইঞ্জিনটি সম্ভাব্য সংঘর্ষগুলি দ্রুত সনাক্ত করে)
- (গেমটি নির্দিষ্ট বস্তুর সঠিক সংঘর্ষগুলি পরীক্ষা করতে ইঞ্জিনকে অবহিত করে) [অবজেক্টের ভেক্টরকে রিটার্ন দেয়]]
- (বস্তু অনুপ্রবেশের গভীরতার দিকে তাকাচ্ছে, পাশাপাশি অন্য বস্তুর পূর্ববর্তী অবস্থানের তুলনায় পূর্ববর্তী অবস্থানের তুলনায়, কোন দিকটি সরে যেতে হবে তা নির্ধারণ করতে)
- (অবজেক্টের গতিবেগের সাথে বস্তুটি সরানো এবং গড়ের গতিবেগ (যদি বস্তুটি চলমান থাকে))


"(বস্তুটি অনুপ্রবেশের গভীরতার সাথে অন্য কোন বস্তুর পূর্ববর্তী অবস্থানের তুলনায় পূর্ববর্তী অবস্থানটি দেখায়, কোন দিকটি স্লাইড করতে হবে তা নির্ধারণ করতে)" এটি সেই অংশ যা আমি আগ্রহী। আপনি কী ব্যাখ্যা করতে পারবেন? .Gif এবং ডায়াগ্রাম দ্বারা প্রদর্শিত পরিস্থিতিতে এটি সফল হয়?
ভিটোরিও রোমিও

আমি এখনো পরিস্থিতি (উচ্চ বেগ ছাড়া) যে এই পদ্ধতি কাজ করে না এটি করেছি।
ultifinitus

ভাল লাগছে, তবে আপনি কীভাবে অনুপ্রবেশগুলি সমাধান করবেন তা বাস্তবে ব্যাখ্যা করতে পারবেন? আপনি কি সর্বদা ক্ষুদ্র অক্ষকে সমাধান করেন? আপনি সংঘর্ষের দিকটি পরীক্ষা করেন?
ভিটোরিও রোমিও

আসলে ছোট অক্ষগুলি কোনও ভাল (প্রাথমিক) যাওয়ার উপায় নয়। এই প্রোগ্রামটিতে। আমি সাধারণত অন্য পক্ষের পাশের বাহিরে আগে কোন দিকে ছিল তার ভিত্তিতে সমাধান করি, এটি সর্বাধিক সাধারণ। যখন এটি ব্যর্থ হয়, তারপরে আমি বেগ এবং গভীরতার ভিত্তিতে যাচাই করি।
আল্টিফিনিটাস

2

ভিডিও গেমগুলিতে আমি প্রোগ্রাম করেছিলাম আপনার অবস্থানটি বৈধ কিনা, তা জানার জন্য একটি ক্রিয়াকলাপ চালানো হয়েছিল। bool ValidPos (int x, int y, int wi, int he);

ফাংশনটি গেমের সমস্ত জ্যামিতির বিপরীতে বাউন্ডিং বক্স (x, y, wi, he) পরীক্ষা করে এবং যদি কোনও ছেদ থাকে তবে মিথ্যা ফিরিয়ে দেয়।

আপনি যদি সরে যেতে চান, ডানদিকে বলুন, প্লেয়ারের অবস্থান নিন, 4 থেকে এক্স যোগ করুন এবং অবস্থানটি বৈধ কিনা তা পরীক্ষা করুন, না হলে +3, + 2 ইত্যাদি দিয়ে পরীক্ষা করুন যতক্ষণ না এটি হয়।

যদি আপনার মাধ্যাকর্ষণও প্রয়োজন হয় তবে আপনার একটি পরিবর্তনশীল দরকার যা যতক্ষণ আপনি মাটিতে আঘাত করবেন না যতক্ষণ না বাড়বে (হিটিং গ্রাউন্ড: ভ্যালিডপোস (x, y + 1, wi, he) == সত্য, y এখানে ইতিবাচক)। যদি আপনি এই দূরত্বটি সরিয়ে নিতে পারেন (যেমন, ValidPos (x, y + মাধ্যাকর্ষণ, ডাব্লু, সত্য)) আপনি যে পতন করছেন, দরকারী কখনও কখনও যখন আপনি যখন পতনের সময় আপনার চরিত্রকে নিয়ন্ত্রণ করতে সক্ষম হন না।

এখন, আপনার সমস্যাটি হ'ল আপনার বিশ্বে এমন অবজেক্ট রয়েছে যা আপনার পুরানো অবস্থানটি এখনও বৈধ কিনা আপনার যাচাই করা দরকার প্রথমে!

যদি এটি না হয় তবে আপনাকে এমন একটি অবস্থানের সন্ধান করতে হবে যা। যদি আইটেমস এনগনাম গেম বিপ্লব প্রতি 2 পিক্সেল বলার চেয়ে দ্রুত সরাতে না পারে তবে আপনাকে (x, y-2) অবস্থানটি (x, y-2) এর পরে (x + 1, y) ইত্যাদি পরীক্ষা করতে হবে position ইত্যাদি (x-2, y-2) থেকে (x + 2, y + 2) এর মধ্যে পুরো স্থানটি পরীক্ষা করা উচিত। যদি কোনও বৈধ অবস্থান না থাকে তবে এর অর্থ আপনি 'পিষিত' হয়েছেন।

আছে HTH

Valmond


আমি আমার গেম মেকার দিনগুলিতে এই পদ্ধতিটি ফিরে ব্যবহার করতাম। আমি এটির গতি বাড়ানোর / উন্নততর অনুসন্ধানগুলির সাথে উন্নত করার উপায়গুলি সম্পর্কে ভাবতে পারি (আপনি যে স্থানটি ভ্রমণ করেছেন তার উপর একটি বাইনারি অনুসন্ধান বলুন, যদিও আপনি যে দূরত্ব এবং জ্যামিতির উপর নির্ভর করে এটি ধীর গতিতে) তবে এই পদ্ধতির মূল অসুবিধা হ'ল সমস্ত সম্ভাব্য সংঘর্ষের বিরুদ্ধে একটি চেক বলার পরিবর্তে, আপনি যে অবস্থানে আছেন তার পরিবর্তন যাচাই করে নিন।
জেফ

"আপনার অবস্থার পরিবর্তন যা যা হয় তা যাচাই করে নিচ্ছেন" দুঃখিত, তবে এর অর্থ কি? বিটিডব্লিউ অবশ্যই গেমটি গতি বাড়ানোর জন্য স্পেস পার্টিশন কৌশল (বিএসপি, অক্ট্রি, কোয়াড্ট্রি, টাইলম্যাপ ইত্যাদি) ব্যবহার করবে তবে আপনাকে সর্বদা এটি করা দরকার (যদি মানচিত্রটি বড় হয়) তবে প্রশ্নটি তবে তা নয় তবে প্লেয়ারকে (সঠিকভাবে) স্থানান্তর করতে ব্যবহৃত অ্যালগরিদম সম্পর্কে।
ভালমন্ড

@ ভালমন্ড আমার মনে হয় @ জেফের অর্থ এই যে আপনি যদি প্লেয়ারটি 10 ​​পিক্সেল বামে চলে যান তবে আপনার 10 টির বেশি সংঘর্ষের সনাক্তকরণ থাকতে পারে।
জোনাথন কনেল

যদি সে কথার অর্থ এটিই হয় তবে সে সঠিক এবং এটি সেভাবে হওয়া উচিত (অন্যথায় আমরা +6 এ থামি এবং +7 না হলে কে বলতে পারে)। কম্পিউটারগুলি দ্রুত, আমি এটি এস 40 (m 200mhz এবং একটি খুব দ্রুত কেভিএম) এ ব্যবহার করেছিলাম এবং এটি একটি কবজির মতো কাজ করে। আপনি সর্বদা প্রাথমিক আলগো অনুকূলকরণের চেষ্টা করতে পারেন তবে এটি সর্বদা আপনাকে ওপি'র মতো কর্নার কেস দেবে।
ভালমন্ড

আমি ঠিক তাই বলতে চেয়েছিলাম
জেফ

2

আমি এর উত্তর দেওয়া শুরু করার আগে আমার কয়েকটি প্রশ্ন রয়েছে। প্রথমত, মূল বাগটিতে আপনি যে দেয়ালগুলিতে আটকে গিয়েছিলেন, সেই বড় টাইলগুলির বিপরীতে individual টাইলগুলি কি বাম স্বতন্ত্র টাইলগুলির ছিল? এবং যদি তারা হয় তবে প্লেয়ারটি কি তাদের মধ্যে আটকে যাচ্ছিল? যদি এই দুটি প্রশ্নের হ্যাঁ হয় তবে কেবলমাত্র আপনার নতুন অবস্থানটি বৈধ কিনা তা নিশ্চিত করুন । এর অর্থ আপনার প্লেয়ারকে কোথায় সরানোর জন্য বলা হচ্ছে সেখানে কোনও সংঘর্ষ রয়েছে কিনা তা আপনাকে পরীক্ষা করতে হবে। তাই ন্যূনতম স্থানচ্যুতি হিসাবে নীচে বর্ণিত সমাধান, এবং তারপর যে উপর ভিত্তি করে আপনার খেলোয়াড় সরানো সে যদি করতে পারেনওখানে যাও. প্রায় নাকের নীচে: পি এটি আসলে অন্য একটি বাগ প্রবর্তন করবে, যা আমি "কর্নার কেস" বলি। মূলত কোণগুলির নিরিখে (নীচের বামের মতো যেখানে অনুভূমিক স্পাইকগুলি আপনার .gif এ বেরিয়ে আসে তবে কোনও স্পাইক না থাকলে) কোনও সংঘাতের সমাধান করতে পারে না, কারণ এটি মনে করে যে আপনি যে রেজোলিউশন উত্পন্ন করেছেন তার কোনওটিই একটি বৈধ অবস্থানের দিকে নিয়ে যায় না to । এটির সমাধানের জন্য, সংঘর্ষটি সমাধান হয়েছে কিনা তার একদম সহজভাবে পাশাপাশি সর্বনিম্ন অনুপ্রবেশ সংক্রান্ত সমস্ত রেজোলিউশনের একটি তালিকা রাখুন। এর পরে, যদি সংঘর্ষের সমাধান না করা হয়, তবে আপনার উত্পন্ন প্রতিটি রেজোলিউশনটি লুপ করুন এবং সর্বাধিক এক্স এবং সর্বাধিক ওয়াই রেজোলিউশনগুলি ট্র্যাক করুন (সর্বাধিক ক্ষেত্রে একই রেজোলিউশন থেকে আসতে হবে না)। তারপরে সেই সর্বাধিকের সংঘর্ষের সমাধান করুন। এটি আপনার সমস্ত সমস্যার পাশাপাশি আমি যে সমস্যার মুখোমুখি হয়েছিল সেগুলি সমাধান করে বলে মনে হচ্ছে।

    List<Vector2> collisions = new List<Vector2>();
        bool resolved = false;
        foreach (Platform p in testPlat)
        {
            Vector2 dif = p.resolveCollision(player.getCollisionMask());

            RectangleF newPos = player.getCollisionMask();

            newPos.X -= dif.X;
            newPos.Y -= dif.Y;


            if (!PlatformCollision(newPos)) //This checks if there's a collision (ie if we're entering an invalid space)
            {
                if (dif.X != 0)
                    player.velocity.X = 0; //Do whatever you want here, I like to stop my player on collisions
                if (dif.Y != 0)
                    player.velocity.Y = 0;

                player.MoveY(-dif.Y);
                player.MoveX(-dif.X);
                resolved = true;
            }
            collisions.Add(dif);
        }

        if (!resolved)
        {
            Vector2 max = Vector2.Zero;

            foreach (Vector2 v in collisions)
            {
                if (Math.Abs(v.X) > Math.Abs(max.X))
                {
                    max.X = v.X;
                }
                if (Math.Abs(v.Y) > Math.Abs(max.Y))
                {
                    max.Y = v.Y;
                }
            }

            player.MoveY(-max.Y);

            if (max.Y != 0)
                player.velocity.Y = 0;
            player.MoveX(-max.X);

            if (max.X != 0)
                player.velocity.X = 0;
        }

আরেকটি প্রশ্ন, আপনি যে স্পাইকগুলি এক টাইল দেখান, বা স্বতন্ত্র টাইলস সেগুলি কী? যদি সেগুলি স্বতন্ত্র পাতলা টাইল হয় তবে আমি নীচে বর্ণিত তুলনায় অনুভূমিক এবং উল্লম্বগুলির জন্য আপনাকে আলাদা পদ্ধতির ব্যবহার করতে হতে পারে। তবে যদি তারা পুরো টাইল হয় তবে এটি কাজ করা উচিত।


ঠিক আছে, সুতরাং মূলত এটিই ট্র্যাভর পাওয়েল বর্ণনা করছিলেন। যেহেতু আপনি কেবল এএবিবি ব্যবহার করছেন, আপনাকে কেবলমাত্র একটি আয়তক্ষেত্র অন্যটিতে কতটা প্রবেশ করেছে তা খুঁজে বের করতে হবে। এটি আপনাকে এক্স অক্ষ এবং ওয়াইয়ের পরিমাণ দেবে the দুটির মধ্যে ন্যূনতম চয়ন করুন এবং আপনার সংঘর্ষক বস্তুকে সেই অক্ষের সাথে নিয়ে যান। আপনাকে এএবিবি সংঘর্ষের সমাধান করতে হবে এটিই। এ জাতীয় সংঘর্ষে আপনাকে একাধিক অক্ষের সাথে চলতে হবে না, তাই প্রথমে কোনটি স্থানান্তরিত হবে সে সম্পর্কে আপনার কখনও বিভ্রান্ত হওয়া উচিত নয়, কারণ আপনি কেবল ন্যূনতম স্থানান্তরিত হবেন।

মেটানেট সফ্টওয়্যারটির এখানে একটি পদ্ধতির একটি ক্লাসিক টিউটোরিয়াল রয়েছে । এটি অন্যান্য আকারেও যায়।

দুটি আয়তক্ষেত্রের ওভারল্যাপ ভেক্টরটি খুঁজতে আমি এখানে তৈরি একটি এক্সএনএ ফাংশন:

    public Point resolveCollision(Rectangle otherRect)
    {
        if (!isCollision(otherRect))
        {
            return Point.Zero;
        }

        int minOtherX = otherRect.X;
        int maxOtherX = otherRect.X + otherRect.Width;

        int minMyX = collisionMask.X;
        int maxMyX = collisionMask.X + collisionMask.Width;

        int minOtherY = otherRect.Y;
        int maxOtherY = otherRect.Y + otherRect.Height;

        int minMyY = collisionMask.Y;
        int maxMyY = collisionMask.Y + collisionMask.Height;

        int dx, dy;

        if (maxOtherX - minMyX < maxMyX - minOtherX)
        {
            dx = (maxOtherX - minMyX);
        }
        else
        {
            dx = -(maxMyX - minOtherX);
        }

        if (maxOtherY - minMyY < maxMyY - minOtherY)
        {
            dy = (maxOtherY - minMyY);
        }
        else
        {
            dy = -(maxMyY - minOtherY);
        }

        if (Math.Abs(dx) < Math.Abs(dy))
            return new Point(dx, 0);
        else
            return new Point(0, dy);
    }

(আমি আশা করি এটি অনুসরণ করা সহজ, কারণ আমি নিশ্চিত যে এটি বাস্তবায়নের আরও ভাল উপায় আছে ...)

আইসক্লিজেশন (আয়তক্ষেত্র) আক্ষরিকভাবে এক্সএনএ এর আয়তক্ষেত্রের জন্য একটি কল। আন্তঃসংশ্লিষ্ট (আয়তক্ষেত্র)।

আমি চলন্ত প্ল্যাটফর্মগুলির সাথে এটি পরীক্ষা করেছি এবং এটি ঠিকঠাকভাবে কাজ করছে বলে মনে হচ্ছে। আমি আপনার .gif এর সাথে আরও কিছু অনুরূপ আরও কিছু পরীক্ষা করবো তা নিশ্চিত করতে এবং যদি এটি কাজ না করে তবে ফিরে রিপোর্ট করুন।



আমি এ বিষয়ে যে মন্তব্য করেছি তার সম্পর্কে আমি সংশয়বাদী, এটি পাতলা প্ল্যাটফর্মগুলির সাথে কাজ করে না। কেন হবে না এমন কোনও কারণ আমি ভাবতে পারি না। এছাড়াও যদি আপনি উত্স চান তবে আমি আপনার জন্য একটি এক্সএনএ প্রকল্প আপলোড করতে পারি
জেফ

হ্যাঁ আমি এটি আরও কিছুটা পরীক্ষা করে দেখছিলাম এবং এটি দেওয়ালে আটকে যাওয়ার একই সমস্যায় ফিরে যায়। এটি কারণ যেখানে দুটি টাইলস একে অপরের সাথে একত্রিত হয়ে যায়, এটি আপনাকে নীচের কারণে এগিয়ে যেতে বলে এবং তারপরে উপরেরটির জন্য (ডানদিকে ডান) বাইরে বেরিয়ে আসে, যদি আপনার y গতিবেগ যথেষ্ট ধীর হয় তবে মাধ্যাকর্ষণ আন্দোলনকে কার্যকরভাবে উপেক্ষা করে । আমি এর একটি সমাধান সন্ধান করতে হবে, আমার মনে হয় এই সমস্যাটি আগে ছিল।
জেফ

ঠিক আছে, আমি আপনার প্রথম সমস্যাটি সমাধানের জন্য অত্যন্ত হ্যাকি উপায় নিয়ে এসেছি। সমাধানটিতে প্রতিটি এএবিবি-র সর্বনিম্ন অনুপ্রবেশ সন্ধান করা, কেবলমাত্র বৃহত্তম এক্স সহ একটির সমাধান করা, তবে দ্বিতীয় পাসটি কেবল বৃহত্তম ওয়াইয়ের সাথে সমাধান করা you're আপনি যখন পিষ্ট হচ্ছেন তখন খারাপ লাগে তবে কাজটি উত্তোলন করে আপনাকে ধাক্কা দেওয়া যায় অনুভূমিকভাবে এবং আপনার মূল স্টিকিং সমস্যাটি চলে গেছে। এটি হ্যাকি, এবং এটি অন্যান্য আকারে কীভাবে অনুবাদ করবে তা আমার কোনও ধারণা নেই। আর একটি সম্ভাবনা হ'ল স্পর্শকৃত জ্যামিতিগুলিকে ldালাই করা, তবে আমি এটি চেষ্টাও করি নি
জেফ

দেয়াল 16x16 টাইলস দিয়ে তৈরি। স্পাইকগুলি একটি 16x16 টাইল। আমি যদি সর্বনিম্ন অক্ষের উপর সমাধান করি তবে জাম্পিং বাগটি ঘটে (চিত্রটি দেখুন)। আপনার "চরম হ্যাকি" সমাধানটি কি .gif-এ প্রদর্শিত পরিস্থিতিটির সাথে কাজ করবে?
ভিটোরিও রোমিও

হ্যাঁ, আমার কাজ করে। আপনার চরিত্রের আকার কি?
জেফ

1

ইহা সাধারণ.

স্পাইকগুলি আবার লিখুন। এটি স্পাইকসের দোষ।

আপনার সংঘর্ষগুলি পৃথক, বাস্তব ইউনিটগুলিতে হওয়া উচিত। যতদূর আমি দেখতে পাচ্ছি সমস্যাটি হ'ল:

1. Player is outside spikes
2. Spikes move into intersection position with the player
3. Player resolves incorrectly

সমস্যাটি ২ য় ধাপে নয়, !!

যদি আপনি জিনিসগুলি শক্ত অনুভব করার চেষ্টা করছেন তবে আপনার আইটেমগুলিকে একে অপরের মধ্যে slুকতে দেওয়া উচিত নয়। একবার আপনি ছেদ করার অবস্থানে থাকলে, আপনি যদি নিজের জায়গাটি হারিয়ে ফেলেন, তবে সমস্যাটি সমাধান করা আরও শক্ত হয়ে যায়।

স্পাইকগুলি খেলোয়াড়ের অস্তিত্বের জন্য আদর্শভাবে যাচাই করা উচিত এবং যখন তারা স্থানান্তরিত হয়, তখন তাকে প্রয়োজনীয় হিসাবে তাকে চাপ দেওয়া উচিত ।

এটি অর্জনের একটি সহজ উপায় প্লেয়ারের জন্য moveXএবং moveYল্যান্ডস্কেপটি বোঝার জন্য ফাংশনগুলির জন্য এবং কোনও খেলোয়াড়কে কোনও নির্দিষ্ট ব-দ্বীপ দ্বারা বা তারা বাধা না দিয়ে যতদূর পারত

সাধারণত তাদের ইভেন্ট লুপ দ্বারা ডাকা হবে। তবে প্লেয়ারকে ধাক্কা দেওয়ার জন্য তাদেরকে বস্তুগুলির দ্বারাও ডাকা যেতে পারে।

function spikes going up:

    move spikes up

    if intersecting player:
        d = player bottom edge + spikes top edge

        player.moveY(-d)
    end if

end function

একথাও ঠিক যে খেলোয়াড় এখনো স্পাইক প্রতিক্রিয়া যদি প্রয়োজন সে মধ্যে যায় তাদের

অতিরিক্ত নিয়ন্ত্রণের নিয়মটি হল, যে কোনও বস্তুর চলার পরে এটি ছেদ ছাড়াই কোনও অবস্থাতেই শেষ হওয়া উচিত। এইভাবে, আপনি যে গোলকিগুলি দেখছেন তা পাওয়া অসম্ভব।


এমন চরম ক্ষেত্রে যেখানে moveYছেদটি সরিয়ে ফেলতে ব্যর্থ হয় (কারণ অন্য দেয়ালটি সেই পথে) আপনি চৌরাস্তার জন্য আবার যাচাই করতে পারেন এবং হয় মুভিএক্স চেষ্টা করে দেখতে পারেন বা কেবল তাকে হত্যা করতে পারেন।
ক্রিস বার্ট-ব্রাউন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.