আধুনিক ওয়েব বিকাশে, ক্লাসিক এবং ওয়েব অ্যাপ্লিকেশনগুলির মধ্যে সীমানা প্রতিদিন ঝাপসা হয়ে আসছে। আজ আমরা ব্রাউজারে শুধুমাত্র ইন্টারেক্টিভ ওয়েবসাইট নয়, পূর্ণাঙ্গ গেমও তৈরি করতে পারি। এটি সম্ভব করে তোলে এমন একটি টুল হল রিঅ্যাক্ট থ্রি ফাইবার লাইব্রেরি - রিঅ্যাক্ট প্রযুক্তি ব্যবহার করে Three.js এর উপর ভিত্তি করে 3D গ্রাফিক্স তৈরি করার একটি শক্তিশালী টুল।
রিঅ্যাক্ট থ্রি ফাইবার হল Three.js- এর উপর একটি মোড়ক যা ওয়েবে 3D গ্রাফিক্স তৈরি করতে React এর গঠন এবং নীতি ব্যবহার করে। এই স্ট্যাকটি ডেভেলপারদের রিঅ্যাক্ট- এর সুবিধা এবং নমনীয়তার সাথে Three.js- এর শক্তিকে একত্রিত করতে দেয়, একটি অ্যাপ্লিকেশন তৈরির প্রক্রিয়াকে আরও স্বজ্ঞাত এবং সংগঠিত করে।
রিঅ্যাক্ট থ্রি ফাইবার- এর কেন্দ্রে এই ধারণা যে আপনি একটি দৃশ্যে যা কিছু তৈরি করেন তা হল একটি প্রতিক্রিয়া উপাদান। এটি বিকাশকারীদের পরিচিত নিদর্শন এবং পদ্ধতিগুলি প্রয়োগ করতে দেয়।
রিঅ্যাক্ট থ্রি ফাইবারের অন্যতম প্রধান সুবিধা হল রিঅ্যাক্ট ইকোসিস্টেমের সাথে এর একীকরণের সহজতা। এই লাইব্রেরি ব্যবহার করার সময় অন্য যেকোন রিঅ্যাক্ট টুল এখনও সহজেই ইন্টিগ্রেট করা যায়।
ওয়েব-গেমডেভ সাম্প্রতিক বছরগুলিতে বড় পরিবর্তনের মধ্য দিয়ে গেছে, সাধারণ 2D ফ্ল্যাশ গেমগুলি থেকে ডেস্কটপ অ্যাপ্লিকেশনগুলির সাথে তুলনীয় জটিল 3D প্রকল্পগুলিতে বিবর্তিত হয়েছে। জনপ্রিয়তা এবং ক্ষমতার এই বৃদ্ধি ওয়েব-গেমডেভকে এমন একটি ক্ষেত্র করে তোলে যা উপেক্ষা করা যায় না।
ওয়েব গেমিংয়ের অন্যতম প্রধান সুবিধা হল এর অ্যাক্সেসযোগ্যতা। খেলোয়াড়দের কোনো অতিরিক্ত সফ্টওয়্যার ডাউনলোড এবং ইনস্টল করার দরকার নেই - শুধু তাদের ব্রাউজারে লিঙ্কটিতে ক্লিক করুন। এটি গেমগুলির বিতরণ এবং প্রচারকে সরল করে, সারা বিশ্বের বিস্তৃত দর্শকদের কাছে তাদের উপলব্ধ করে।
অবশেষে, ওয়েব গেম ডেভেলপারদের জন্য পরিচিত প্রযুক্তি ব্যবহার করে গেমডেভে তাদের হাত চেষ্টা করার জন্য একটি দুর্দান্ত উপায় হতে পারে। উপলব্ধ সরঞ্জাম এবং লাইব্রেরিগুলির জন্য ধন্যবাদ, এমনকি 3D গ্রাফিক্সের অভিজ্ঞতা ছাড়াই, আকর্ষণীয় এবং উচ্চ-মানের প্রকল্পগুলি তৈরি করা সম্ভব!
আধুনিক ব্রাউজারগুলি অনেক দূর এগিয়েছে, জটিল অ্যাপ্লিকেশন এবং গেমগুলি চালানোর জন্য মোটামুটি সহজ ওয়েব ব্রাউজিং সরঞ্জাম থেকে শক্তিশালী প্ল্যাটফর্মে বিবর্তিত হয়েছে। ক্রোম , ফায়ারফক্স , এজ এবং অন্যান্যগুলির মতো প্রধান ব্রাউজারগুলিকে ক্রমাগত অপ্টিমাইজ করা হচ্ছে এবং উন্নত কর্মক্ষমতা নিশ্চিত করার জন্য উন্নত করা হচ্ছে, যা তাদের জটিল অ্যাপ্লিকেশনগুলি বিকাশের জন্য একটি আদর্শ প্ল্যাটফর্ম করে তুলেছে৷
ব্রাউজার-ভিত্তিক গেমিং-এর বিকাশে ইন্ধন জোগায় এমন একটি মূল টুল হল WebGL । এই মানটি বিকাশকারীদের হার্ডওয়্যার গ্রাফিক্স ত্বরণ ব্যবহার করার অনুমতি দেয়, যা 3D গেমগুলির কার্যকারিতা উল্লেখযোগ্যভাবে উন্নত করে। অন্যান্য webAPI-এর সাথে একত্রে, WebGL ব্রাউজারে সরাসরি চিত্তাকর্ষক ওয়েব অ্যাপ্লিকেশন তৈরি করার জন্য নতুন সম্ভাবনা উন্মুক্ত করে।
তবুও, ব্রাউজারের জন্য গেমগুলি তৈরি করার সময়, বিভিন্ন কর্মক্ষমতার দিকগুলি বিবেচনা করা অত্যন্ত গুরুত্বপূর্ণ: রিসোর্স অপ্টিমাইজেশন, মেমরি ম্যানেজমেন্ট এবং বিভিন্ন ডিভাইসের জন্য অভিযোজন হল সমস্ত মূল বিষয় যা একটি প্রকল্পের সাফল্যকে প্রভাবিত করতে পারে৷
যাইহোক, শব্দ এবং তত্ত্ব এক জিনিস, কিন্তু বাস্তব অভিজ্ঞতা একেবারে অন্য। ওয়েব গেম ডেভেলপমেন্টের সম্পূর্ণ সম্ভাবনাকে সত্যিই বুঝতে এবং উপলব্ধি করতে, ডেভেলপমেন্ট প্রক্রিয়ায় নিজেকে নিমজ্জিত করাই সবচেয়ে ভালো উপায়। অতএব, সফল ওয়েব গেম বিকাশের উদাহরণ হিসাবে, আমরা আমাদের নিজস্ব গেম তৈরি করব। এই প্রক্রিয়াটি আমাদের বিকাশের মূল দিকগুলি শিখতে, বাস্তব সমস্যার মুখোমুখি হতে এবং সেগুলির সমাধান খুঁজে পেতে এবং ওয়েব গেম ডেভেলপমেন্ট প্ল্যাটফর্ম কতটা শক্তিশালী এবং নমনীয় হতে পারে তা দেখতে অনুমতি দেবে।
নিবন্ধগুলির একটি সিরিজে, আমরা এই লাইব্রেরির বৈশিষ্ট্যগুলি ব্যবহার করে কীভাবে একজন প্রথম-ব্যক্তি শ্যুটার তৈরি করতে হয় তা দেখব এবং ওয়েব-গেমডেভের উত্তেজনাপূর্ণ জগতে ডুব দিতে পারি!
GitHub- এ সংগ্রহস্থল
এখন, শুরু করা যাক!
প্রথমত, আমাদের একটি প্রতিক্রিয়া প্রকল্প টেমপ্লেট প্রয়োজন হবে। তাহলে এর ইন্সটল করে শুরু করা যাক।
npm create vite@latest
অতিরিক্ত npm প্যাকেজ ইনস্টল করুন।
npm install three @react-three/fiber @react-three/drei @react three/rapier zustand @tweenjs/tween.js
তারপর আমাদের প্রকল্প থেকে অপ্রয়োজনীয় সবকিছু মুছে ফেলুন ।
main.jsx ফাইলে, একটি ডিভ উপাদান যোগ করুন যা পৃষ্ঠায় একটি সুযোগ হিসাবে প্রদর্শিত হবে। একটি ক্যানভাস উপাদান সন্নিবেশ করুন এবং ক্যামেরার দৃশ্যের ক্ষেত্র সেট করুন। ক্যানভাস কম্পোনেন্টের ভিতরে অ্যাপ কম্পোনেন্ট রাখুন।
UI উপাদানগুলিকে স্ক্রিনের পূর্ণ উচ্চতায় প্রসারিত করতে এবং স্ক্রিনের কেন্দ্রে একটি বৃত্ত হিসাবে স্কোপ প্রদর্শন করতে index.css- এ শৈলী যুক্ত করা যাক।
অ্যাপ কম্পোনেন্টে আমরা একটি স্কাই কম্পোনেন্ট যোগ করি, যা আমাদের গেমের দৃশ্যের পটভূমিতে আকাশ আকারে প্রদর্শিত হবে।
আসুন একটি গ্রাউন্ড কম্পোনেন্ট তৈরি করি এবং এটি অ্যাপ কম্পোনেন্টে রাখি।
গ্রাউন্ডে , একটি সমতল পৃষ্ঠের উপাদান তৈরি করুন। Y অক্ষে এটিকে নিচের দিকে নিয়ে যান যাতে এই সমতলটি ক্যামেরার দৃশ্যের ক্ষেত্রে থাকে। এবং এটিকে অনুভূমিক করতে X অক্ষের উপর প্লেনটি ফ্লিপ করুন।
যদিও আমরা উপাদানের রঙ হিসাবে ধূসরকে নির্দিষ্ট করেছি, প্লেনটি সম্পূর্ণ কালো দেখায়।
ডিফল্টরূপে, দৃশ্যে কোন আলো নেই, তাই আসুন একটি আলোর উৎস অ্যাম্বিয়েন্টলাইট যোগ করি, যা বস্তুটিকে চারদিক থেকে আলোকিত করে এবং নির্দেশিত মরীচি নেই। একটি পরামিতি হিসাবে আলোর তীব্রতা সেট করুন।
মেঝে পৃষ্ঠ একজাত না দেখতে, আমরা জমিন যোগ করা হবে. সমস্ত পৃষ্ঠ বরাবর পুনরাবৃত্তি কোষের আকারে মেঝে পৃষ্ঠের একটি প্যাটার্ন তৈরি করুন।
সম্পদ ফোল্ডারে একটি টেক্সচার সহ একটি PNG ছবি যোগ করুন।
দৃশ্যে একটি টেক্সচার লোড করতে, আসুন @react-three/drei প্যাকেজ থেকে useTexture হুক ব্যবহার করি। এবং হুকের প্যারামিটার হিসাবে আমরা ফাইলে আমদানি করা টেক্সচার ইমেজটি পাস করব। অনুভূমিক অক্ষগুলিতে চিত্রটির পুনরাবৃত্তি সেট করুন।
@react-three/drei প্যাকেজ থেকে PointerLockControls উপাদান ব্যবহার করে, পর্দায় কার্সারটি ঠিক করুন যাতে আপনি মাউস নাড়ালে এটি নড়াচড়া না করে, তবে দৃশ্যে ক্যামেরার অবস্থান পরিবর্তন করে।
গ্রাউন্ড কম্পোনেন্টের জন্য একটি ছোট সম্পাদনা করা যাক।
স্পষ্টতার জন্য, দৃশ্যটিতে একটি সাধারণ ঘনক যোগ করা যাক।
<mesh position={[0, 3, -5]}> <boxGeometry /> </mesh>
এই মুহূর্তে তিনি শুধু মহাকাশে ঝুলছে.
দৃশ্যে "পদার্থবিদ্যা" যোগ করতে @react-three/rapier প্যাকেজ থেকে পদার্থবিজ্ঞানের উপাদান ব্যবহার করুন। একটি প্যারামিটার হিসাবে, মাধ্যাকর্ষণ ক্ষেত্রটি কনফিগার করুন, যেখানে আমরা অক্ষ বরাবর মহাকর্ষীয় বল সেট করি।
<Physics gravity={[0, -20, 0]}> <Ground /> <mesh position={[0, 3, -5]}> <boxGeometry /> </mesh> </Physics>
যাইহোক, আমাদের কিউব পদার্থবিদ্যা উপাদানের ভিতরে আছে, কিন্তু কিছুই হবে না. কিউবটিকে একটি বাস্তব ভৌত বস্তুর মতো আচরণ করতে, আমাদের এটিকে @react-three/rapier প্যাকেজ থেকে RigidBody কম্পোনেন্টে মোড়ানো দরকার।
এর পরে, আমরা অবিলম্বে দেখতে পাব যে প্রতিবার পৃষ্ঠাটি পুনরায় লোড হওয়ার সাথে সাথে ঘনকটি মাধ্যাকর্ষণ শক্তির প্রভাবে নিচে পড়ে যায়।
তবে এখন আরেকটি কাজ রয়েছে - মেঝেটিকে এমন একটি বস্তু তৈরি করা প্রয়োজন যার সাথে ঘনক্ষেত্রটি যোগাযোগ করতে পারে এবং এর বাইরে এটি পড়বে না।
আসুন গ্রাউন্ড কম্পোনেন্টে ফিরে যাই এবং মেঝে পৃষ্ঠের উপর একটি মোড়ক হিসাবে একটি RigidBody উপাদান যোগ করি।
এখন পড়ার সময়, কিউবটি একটি বাস্তব ভৌত বস্তুর মতো মেঝেতে থাকে।
আসুন একটি প্লেয়ার উপাদান তৈরি করি যা দৃশ্যের চরিত্রকে নিয়ন্ত্রণ করবে।
অক্ষরটি যোগ করা ঘনক্ষেত্রের মতো একই ভৌত বস্তু, তাই এটি অবশ্যই মেঝে পৃষ্ঠের সাথে দৃশ্যের ঘনক্ষেত্রের সাথে যোগাযোগ করবে। এজন্য আমরা RigidBody উপাদান যোগ করি। এবং ক্যাপসুল আকারে চরিত্র তৈরি করা যাক।
প্লেয়ার উপাদানটি পদার্থবিদ্যা উপাদানের ভিতরে রাখুন।
এখন আমাদের চরিত্র দৃশ্যপটে হাজির হয়েছে।
অক্ষরটি WASD কী ব্যবহার করে নিয়ন্ত্রণ করা হবে এবং স্পেসবার ব্যবহার করে লাফ দেওয়া হবে।
আমাদের নিজস্ব প্রতিক্রিয়া-হুক দিয়ে, আমরা চরিত্রটি সরানোর যুক্তি প্রয়োগ করি।
আসুন একটি hooks.js ফাইল তৈরি করি এবং সেখানে একটি নতুন usePersonControls ফাংশন যোগ করি।
চলুন একটি অবজেক্টকে বিন্যাসে সংজ্ঞায়িত করি {"keycode": "Action to be performed"}। এরপরে, কীবোর্ড কী টিপে এবং প্রকাশ করার জন্য ইভেন্ট হ্যান্ডলার যোগ করুন। যখন হ্যান্ডলারগুলি ট্রিগার করা হয়, তখন আমরা সঞ্চালিত বর্তমান ক্রিয়াগুলি নির্ধারণ করব এবং তাদের সক্রিয় অবস্থা আপডেট করব। চূড়ান্ত ফলাফল হিসাবে, হুকটি {"অ্যাকশন ইন প্রগ্রেস": "স্ট্যাটাস"} ফর্ম্যাটে একটি বস্তু ফেরত দেবে।
UsePersonControls হুক প্রয়োগ করার পরে, অক্ষর নিয়ন্ত্রণ করার সময় এটি ব্যবহার করা উচিত। প্লেয়ার কম্পোনেন্টে আমরা মোশন স্টেট ট্র্যাকিং যোগ করব এবং চরিত্রের মুভমেন্ট ডিরেকশনের ভেক্টর আপডেট করব।
আমরা ভেরিয়েবলগুলিকেও সংজ্ঞায়িত করব যা আন্দোলনের দিকনির্দেশের অবস্থা সংরক্ষণ করবে।
চরিত্রের অবস্থান আপডেট করতে, আসুন @react-three/fiber প্যাকেজ দ্বারা প্রদত্ত ফ্রেম ব্যবহার করি। এই হুক রিকোয়েস্ট অ্যানিমেশনফ্রেমের মতোই কাজ করে এবং প্রতি সেকেন্ডে প্রায় 60 বার ফাংশনের বডি এক্সিকিউট করে।
কোড ব্যাখ্যা:
1. const playerRef = useRef(); প্লেয়ার অবজেক্টের জন্য একটি লিঙ্ক তৈরি করুন। এই লিঙ্কটি দৃশ্যে প্লেয়ার অবজেক্টের সাথে সরাসরি মিথস্ক্রিয়া করার অনুমতি দেবে।
2. const { ফরোয়ার্ড, ব্যাকওয়ার্ড, বাম, ডান, লাফ} = usePersonControls(); যখন একটি হুক ব্যবহার করা হয়, তখন প্লেয়ার দ্বারা বর্তমানে কোন কন্ট্রোল বোতাম টিপানো হয়েছে তা নির্দেশ করে বুলিয়ান মান সহ একটি বস্তু ফিরে আসে।
3. useFrame((state) => { ... }); অ্যানিমেশনের প্রতিটি ফ্রেমে হুক বলা হয়। এই হুকের ভিতরে, প্লেয়ারের অবস্থান এবং রৈখিক বেগ আপডেট করা হয়।
4. যদি (!playerRef.current) ফিরে আসে; প্লেয়ার অবজেক্টের উপস্থিতি পরীক্ষা করে। কোনো প্লেয়ার অবজেক্ট না থাকলে, ত্রুটি এড়াতে ফাংশনটি কার্যকর করা বন্ধ করবে।
5. const বেগ = playerRef.current.linvel(); প্লেয়ারের বর্তমান রৈখিক বেগ পান।
6. frontVector.set(0, 0, পশ্চাদমুখী - এগিয়ে); চাপা বোতামের উপর ভিত্তি করে ফরোয়ার্ড/পেছনগামী গতি ভেক্টর সেট করুন।
7. sideVector.set(বাম - ডান, 0, 0); বাম/ডান আন্দোলন ভেক্টর সেট করুন।
8. দিক। সাবভেক্টর (সামনের ভেক্টর, সাইডভেক্টর)। নরমালাইজ()। মাল্টিপ্লাইস্ক্যালার(MOVE_SPEED); মুভমেন্ট ভেক্টরগুলি বিয়োগ করে, ফলাফলকে স্বাভাবিক করে (যাতে ভেক্টরের দৈর্ঘ্য 1 হয়) এবং আন্দোলনের গতি ধ্রুবক দ্বারা গুণ করে প্লেয়ার আন্দোলনের চূড়ান্ত ভেক্টর গণনা করুন।
9. playerRef.current.wakeUp(); প্লেয়ার অবজেক্টকে "জাগিয়ে দেয়" যাতে এটি পরিবর্তনের প্রতিক্রিয়া জানায়। আপনি যদি এই পদ্ধতিটি ব্যবহার না করেন, কিছু সময়ের পরে বস্তুটি "ঘুম" হবে এবং অবস্থান পরিবর্তনে প্রতিক্রিয়া দেখাবে না।
10. playerRef.current.setLinvel({ x: direction.x, y: velocity.y, z: direction.z }); গতিবিধির গণনাকৃত দিকনির্দেশের উপর ভিত্তি করে প্লেয়ারের নতুন রৈখিক বেগ সেট করুন এবং বর্তমান উল্লম্ব বেগ রাখুন (যাতে লাফ বা পতন প্রভাবিত না হয়)।
ফলস্বরূপ, WASD কী টিপলে, চরিত্রটি দৃশ্যের চারপাশে ঘুরতে শুরু করে। তিনি ঘনক্ষেত্রের সাথেও যোগাযোগ করতে পারেন, কারণ তারা উভয়ই ভৌত বস্তু।
জাম্প বাস্তবায়নের জন্য, আসুন @dimforge/rapier3d-compat এবং @react-three/rapier প্যাকেজ থেকে কার্যকারিতা ব্যবহার করি। এই উদাহরণে, আসুন পরীক্ষা করি যে অক্ষরটি মাটিতে রয়েছে এবং জাম্প কী টিপানো হয়েছে। এই ক্ষেত্রে, আমরা Y-অক্ষের উপর অক্ষরের দিকনির্দেশ এবং ত্বরণ বল সেট করি।
প্লেয়ারের জন্য আমরা সমস্ত অক্ষে ভর এবং ব্লক ঘূর্ণন যোগ করব, যাতে দৃশ্যের অন্যান্য বস্তুর সাথে সংঘর্ষের সময় সে বিভিন্ন দিক থেকে পড়ে না যায়।
কোড ব্যাখ্যা:
- const world = rapier.world; Rapier পদার্থবিদ্যা ইঞ্জিন দৃশ্য অ্যাক্সেস লাভ. এটিতে সমস্ত ভৌত বস্তু রয়েছে এবং তাদের মিথস্ক্রিয়া পরিচালনা করে।
- const ray = world.castRay(নতুন RAPIER.Ray(playerRef.current.translation(), { x: 0, y: -1, z: 0 })); এখানেই "রেকাস্টিং" (রেকাস্টিং) হয়। একটি রশ্মি তৈরি করা হয় যা প্লেয়ারের বর্তমান অবস্থান থেকে শুরু হয় এবং y-অক্ষকে নির্দেশ করে। এই রশ্মি দৃশ্যের কোন বস্তুর সাথে ছেদ করে কিনা তা নির্ধারণ করতে দৃশ্যে "কাস্ট" করা হয়।
- const grounded = ray && ray.collider && Math.abs(ray.toi) <= 1.5; খেলোয়াড় মাটিতে আছে কিনা তা পরীক্ষা করা হয়:
- রশ্মি - রশ্মি তৈরি হয়েছিল কিনা;
- ray.collider - দৃশ্যের কোন বস্তুর সাথে রশ্মির সংঘর্ষ হয়েছে কিনা;
- Math.abs(ray.toi) - রশ্মির "এক্সপোজার সময়"। যদি এই মানটি প্রদত্ত মানের থেকে কম বা সমান হয় তবে এটি নির্দেশ করতে পারে যে প্লেয়ারটি "ভূমিতে" বিবেচনা করার জন্য পৃষ্ঠের যথেষ্ট কাছাকাছি রয়েছে।
আপনাকে গ্রাউন্ড কম্পোনেন্টও পরিবর্তন করতে হবে যাতে "ল্যান্ডিং" স্ট্যাটাস নির্ধারণের জন্য রেট্রেসড অ্যালগরিদম সঠিকভাবে কাজ করে, একটি ফিজিক্যাল অবজেক্ট যোগ করে যা দৃশ্যের অন্যান্য বস্তুর সাথে ইন্টারঅ্যাক্ট করবে।
দৃশ্যটি আরও ভালোভাবে দেখার জন্য ক্যামেরাটি একটু উঁচু করা যাক।
সেকশন কোড
ক্যামেরা সরানোর জন্য, আমরা প্লেয়ারের বর্তমান অবস্থান পাব এবং প্রতিবার ফ্রেম রিফ্রেশ করার সময় ক্যামেরার অবস্থান পরিবর্তন করব। এবং চরিত্রটি ঠিক ট্র্যাজেক্টোরি বরাবর সরানোর জন্য, যেখানে ক্যামেরা নির্দেশিত হয়, আমাদের যোগ করতে হবে applyEuler ।
কোড ব্যাখ্যা:
applyEuler পদ্ধতি নির্দিষ্ট অয়লার কোণের উপর ভিত্তি করে একটি ভেক্টরে ঘূর্ণন প্রয়োগ করে। এই ক্ষেত্রে, ক্যামেরা ঘূর্ণন দিক ভেক্টর প্রয়োগ করা হয়. এটি ক্যামেরার অভিযোজন সাপেক্ষে গতির সাথে মেলানোর জন্য ব্যবহৃত হয়, যাতে প্লেয়ারটি ক্যামেরাটি যে দিকে ঘোরানো হয় সেদিকে চলে।
আসুন প্লেয়ারের আকার সামান্য সামঞ্জস্য করি এবং এটিকে ঘনক্ষেত্রের সাপেক্ষে লম্বা করি, ক্যাপসুলকোলাইডারের আকার বৃদ্ধি করি এবং "জাম্প" লজিক ঠিক করি।
সেকশন কোড
দৃশ্যটি সম্পূর্ণ খালি মনে না করার জন্য, আসুন কিউব জেনারেশন যোগ করি। json ফাইলে, প্রতিটি কিউবের স্থানাঙ্ক তালিকাভুক্ত করুন এবং তারপরে তাদের দৃশ্যে প্রদর্শন করুন। এটি করার জন্য, একটি ফাইল তৈরি করুন cubes.json , যেখানে আমরা স্থানাঙ্কগুলির একটি অ্যারের তালিকা করব।
[ [0, 0, -7], [2, 0, -7], [4, 0, -7], [6, 0, -7], [8, 0, -7], [10, 0, -7] ]
Cube.jsx ফাইলে, একটি কিউব উপাদান তৈরি করুন, যা একটি লুপে কিউব তৈরি করবে। এবং কিউব কম্পোনেন্ট সরাসরি জেনারেটেড অবজেক্ট হবে।
import {RigidBody} from "@react-three/rapier"; import cubes from "./cubes.json"; export const Cubes = () => { return cubes.map((coords, index) => <Cube key={index} position={coords} />); } const Cube = (props) => { return ( <RigidBody {...props}> <mesh castShadow receiveShadow> <meshStandardMaterial color="white" /> <boxGeometry /> </mesh> </RigidBody> ); }
আগের একক কিউব মুছে দিয়ে অ্যাপ কম্পোনেন্টে তৈরি করা কিউবস কম্পোনেন্ট যোগ করা যাক।
এখন দৃশ্যে একটি 3D মডেল যোগ করা যাক। চরিত্রের জন্য একটি অস্ত্র মডেল যোগ করা যাক. আসুন একটি 3D মডেল খুঁজতে শুরু করা যাক। উদাহরণ স্বরূপ, এইটা ধরা যাক।
মডেলটিকে GLTF ফরম্যাটে ডাউনলোড করুন এবং প্রকল্পের মূলে সংরক্ষণাগারটি আনপ্যাক করুন।
বিন্যাস পেতে আমাদের দৃশ্যে মডেল আমদানি করতে হবে, আমাদের gltf-pipeline অ্যাড-অন প্যাকেজ ইনস্টল করতে হবে।
npm i -D gltf-pipeline
gltf-পাইপলাইন প্যাকেজ ব্যবহার করে, মডেলটিকে GLTF ফর্ম্যাট থেকে GLB ফর্ম্যাটে পুনঃরূপান্তর করুন, যেহেতু এই ফর্ম্যাটে সমস্ত মডেল ডেটা একটি ফাইলে স্থাপন করা হয়৷ উত্পন্ন ফাইলের জন্য একটি আউটপুট ডিরেক্টরি হিসাবে আমরা সর্বজনীন ফোল্ডারটি নির্দিষ্ট করি।
gltf-pipeline -i weapon/scene.gltf -o public/weapon.glb
তারপরে দৃশ্যে যুক্ত করার জন্য আমাদের একটি প্রতিক্রিয়া উপাদান তৈরি করতে হবে যাতে এই মডেলের মার্কআপ থাকবে। আসুন @react-three/fiber ডেভেলপারদের অফিসিয়াল রিসোর্স ব্যবহার করি।
কনভার্টারে যাওয়ার জন্য আপনাকে রূপান্তরিত weapon.glb ফাইলটি লোড করতে হবে।
ড্র্যাগ অ্যান্ড ড্রপ বা এক্সপ্লোরার অনুসন্ধান ব্যবহার করে, এই ফাইলটি খুঁজুন এবং এটি ডাউনলোড করুন।
কনভার্টারে আমরা জেনারেটেড রিঅ্যাক্ট-কম্পোনেন্ট দেখতে পাব, যে কোডটি আমরা আমাদের প্রোজেক্টে একটি নতুন ফাইল WeaponModel.jsx এ স্থানান্তর করব, কম্পোনেন্টের নাম পরিবর্তন করে ফাইলের মতো একই নামে।
এখন তৈরি করা মডেলটি দৃশ্যে আমদানি করা যাক। App.jsx ফাইলে WeaponModel কম্পোনেন্ট যোগ করুন।
আমাদের দৃশ্যের এই মুহুর্তে, কোনো বস্তুই ছায়া ফেলছে না।
দৃশ্যে ছায়া সক্রিয় করতে আপনাকে ক্যানভাস উপাদানটিতে ছায়ার বৈশিষ্ট্য যোগ করতে হবে।
এর পরে, আমাদের একটি নতুন আলোর উত্স যোগ করতে হবে। আমাদের ইতিমধ্যে দৃশ্যে পরিবেষ্টিত আলো থাকা সত্ত্বেও, এটি বস্তুর জন্য ছায়া তৈরি করতে পারে না, কারণ এটির একটি দিকনির্দেশক আলোর মরীচি নেই। সুতরাং আসুন একটি নতুন আলোর উত্স যোগ করি যার নাম দিশাগত আলো এবং এটি কনফিগার করি। " কাস্ট " শ্যাডো মোড সক্রিয় করার বৈশিষ্ট্য হল কাস্টশ্যাডো । এটি এই প্যারামিটারের সংযোজন যা নির্দেশ করে যে এই বস্তুটি অন্যান্য বস্তুর উপর ছায়া ফেলতে পারে।
এর পরে, গ্রাউন্ড কম্পোনেন্টে আরেকটি অ্যাট্রিবিউট রিসিভশ্যাডো যোগ করা যাক, যার অর্থ হল দৃশ্যের উপাদানটি নিজের উপর ছায়া গ্রহণ করতে এবং প্রদর্শন করতে পারে।
দৃশ্যের অন্যান্য বস্তুতে অনুরূপ গুণাবলী যোগ করা উচিত: কিউব এবং প্লেয়ার। কিউবগুলির জন্য আমরা কাস্টশ্যাডো এবং রিসিভশ্যাডো যুক্ত করব, কারণ তারা উভয়ই ছায়া কাস্ট এবং গ্রহণ করতে পারে এবং প্লেয়ারের জন্য আমরা কেবল কাস্টশ্যাডো যুক্ত করব।
প্লেয়ারের জন্য cast Shadow যোগ করা যাক।
কাস্টশ্যাডো যোগ করুন এবং কিউবের জন্য শ্যাডো গ্রহণ করুন ।
আপনি যদি এখন ঘনিষ্ঠভাবে লক্ষ্য করেন তবে আপনি দেখতে পাবেন যে পৃষ্ঠের ক্ষেত্রফল যার উপর ছায়াটি নিক্ষেপ করা হয়েছে তা বেশ ছোট। এবং এই এলাকা অতিক্রম করার সময়, ছায়া সহজভাবে কাটা হয়।
এর কারণ হল ডিফল্টরূপে ক্যামেরা ডিরেকশনাল লাইট থেকে প্রদর্শিত ছায়াগুলির একটি ছোট এলাকা ক্যাপচার করে। দৃশ্যমানতার এই ক্ষেত্রটিকে প্রসারিত করতে আমরা অতিরিক্ত বৈশিষ্ট্যগুলি ছায়া-ক্যামেরা-(শীর্ষ, নীচে, বাম, ডান) যোগ করে নির্দেশমূলক আলোক উপাদানটির জন্য করতে পারি। এই বৈশিষ্ট্যগুলি যোগ করার পরে, ছায়াটি কিছুটা ঝাপসা হয়ে যাবে। গুণমান উন্নত করতে, আমরা ছায়া-ম্যাপসাইজ অ্যাট্রিবিউট যোগ করব।
এখন প্রথম ব্যক্তি অস্ত্র প্রদর্শন যোগ করা যাক. একটি নতুন অস্ত্র উপাদান তৈরি করুন, যাতে অস্ত্রের আচরণের যুক্তি এবং 3D মডেল নিজেই থাকবে।
import {WeaponModel} from "./WeaponModel.jsx"; export const Weapon = (props) => { return ( <group {...props}> <WeaponModel /> </group> ); }
আসুন এই উপাদানটিকে অক্ষরের RigidBody- এর মতো একই স্তরে রাখি এবং useFrame হুকে আমরা ক্যামেরা থেকে মানগুলির অবস্থানের উপর ভিত্তি করে অবস্থান এবং ঘূর্ণন কোণ সেট করব।
চরিত্রের চালচলনকে আরও স্বাভাবিক করতে, আমরা নড়াচড়া করার সময় অস্ত্রের সামান্য নড়াচড়া যোগ করব। অ্যানিমেশন তৈরি করতে আমরা ইনস্টল করা tween.js লাইব্রেরি ব্যবহার করব।
ওয়েপন কম্পোনেন্টটি একটি গ্রুপ ট্যাগে মোড়ানো হবে যাতে আপনি UseRef হুকের মাধ্যমে এটিতে একটি রেফারেন্স যোগ করতে পারেন।
অ্যানিমেশন সংরক্ষণ করতে কিছু useState যোগ করা যাক.
অ্যানিমেশন শুরু করার জন্য একটি ফাংশন তৈরি করা যাক।
কোড ব্যাখ্যা:
- const twSwayingAnimation = new TWEEN.Tween(currentPosition) ... একটি বস্তুর একটি অ্যানিমেশন তৈরি করা হচ্ছে "সুইং" এর বর্তমান অবস্থান থেকে একটি নতুন অবস্থানে।
- const twSwayingBackAnimation = new TWEEN.Tween(currentPosition) ... প্রথম অ্যানিমেশন শেষ হওয়ার পর তার প্রারম্ভিক অবস্থানে ফিরে আসা বস্তুর একটি অ্যানিমেশন তৈরি করা।
- twSwayingAnimation.chain(twSwayingBackAnimation); দুটি অ্যানিমেশন সংযুক্ত করা যাতে প্রথম অ্যানিমেশন সম্পূর্ণ হলে, দ্বিতীয় অ্যানিমেশন স্বয়ংক্রিয়ভাবে শুরু হয়।
useEffect- এ আমরা অ্যানিমেশন ইনিশিয়ালাইজেশন ফাংশন বলি।
এখন আন্দোলনটি ঘটে এমন মুহূর্তটি নির্ধারণ করা প্রয়োজন। এটি চরিত্রের দিকনির্দেশের বর্তমান ভেক্টর নির্ধারণ করে করা যেতে পারে।
যদি অক্ষর আন্দোলন ঘটে, আমরা অ্যানিমেশনটি রিফ্রেশ করব এবং শেষ হয়ে গেলে এটি আবার চালাব।
কোড ব্যাখ্যা:
- const isMoving = direction.length() > 0; এখানে বস্তুর নড়াচড়া অবস্থা পরীক্ষা করা হয়। যদি দিক ভেক্টরের দৈর্ঘ্য 0-এর বেশি হয়, তাহলে এর মানে হল যে বস্তুটির চলাচলের দিক রয়েছে।
- যদি (isMoving && isSwayingAnimationFinished) { ... } যদি বস্তুটি চলমান থাকে এবং "সুইংিং" অ্যানিমেশন শেষ হয় তবে এই অবস্থাটি কার্যকর করা হয়।
অ্যাপ কম্পোনেন্টে, আসুন একটি ইউজফ্রেম যোগ করি যেখানে আমরা টুইন অ্যানিমেশন আপডেট করব।
TWEEN.update() TWEEN.js লাইব্রেরিতে সমস্ত সক্রিয় অ্যানিমেশন আপডেট করে। এই পদ্ধতিটি প্রতিটি অ্যানিমেশন ফ্রেমে বলা হয় যাতে সমস্ত অ্যানিমেশন সুচারুভাবে চালানো হয়।
বিভাগ কোড:
আমাদের সেই মুহূর্তটি সংজ্ঞায়িত করতে হবে যখন একটি শট গুলি করা হয় - অর্থাৎ, যখন মাউস বোতাম টিপে। চলুন এই অবস্থাটি সংরক্ষণ করতে useState যোগ করি, অস্ত্র বস্তুর একটি রেফারেন্স সংরক্ষণ করার জন্য রেফ ব্যবহার করি এবং মাউস বোতাম টিপতে এবং ছেড়ে দেওয়ার জন্য দুটি ইভেন্ট হ্যান্ডলার যোগ করি।
মাউস বোতামে ক্লিক করার সময় একটি রিকোয়েল অ্যানিমেশন প্রয়োগ করা যাক। আমরা এই উদ্দেশ্যে tween.js লাইব্রেরি ব্যবহার করব।
চলুন রিকোয়েল ফোর্স এবং অ্যানিমেশন সময়কালের জন্য ধ্রুবক সংজ্ঞায়িত করি।
ওয়েপন উইগল অ্যানিমেশনের মতো, আমরা রিকোয়েলের জন্য দুটি ইউজ স্টেট স্টেট যোগ করি এবং হোম পজিশন অ্যানিমেশনে ফিরে যাই এবং অ্যানিমেশন শেষ স্ট্যাটাস সহ একটি স্টেট।
চলুন রিকোয়েল অ্যানিমেশনের একটি র্যান্ডম ভেক্টর পেতে ফাংশন তৈরি করি - generateRecoilOffset এবং generateNewPositionOfRecoil ।
রিকোয়েল অ্যানিমেশন শুরু করার জন্য একটি ফাংশন তৈরি করুন। আমরা useEffect যোগ করব, যেখানে আমরা "শট" অবস্থাকে নির্ভরতা হিসাবে নির্দিষ্ট করব, যাতে প্রতিটি শটে অ্যানিমেশন আবার শুরু হয় এবং নতুন শেষ স্থানাঙ্ক তৈরি হয়।
এবং useFrame- এ, গুলি চালানোর জন্য মাউস কী "ধরে রাখার" জন্য একটি চেক যোগ করা যাক, যাতে কীটি প্রকাশ না হওয়া পর্যন্ত ফায়ারিং অ্যানিমেশন বন্ধ না হয়।
চরিত্রের জন্য "নিষ্ক্রিয়তা" এর অ্যানিমেশনটি উপলব্ধি করুন, যাতে "ঝুলন্ত" গেমটির কোনও অনুভূতি না থাকে।
এটি করার জন্য, আসুন useState এর মাধ্যমে কিছু নতুন রাজ্য যোগ করি।
স্টেট থেকে মানগুলি ব্যবহার করার জন্য "উইগল" অ্যানিমেশনের প্রারম্ভিকতা ঠিক করা যাক। ধারণাটি হল যে বিভিন্ন রাজ্য: হাঁটা বা থামানো, অ্যানিমেশনের জন্য বিভিন্ন মান ব্যবহার করবে এবং প্রতিবার অ্যানিমেশনটি প্রথমে শুরু হবে।
এই অংশে আমরা দৃশ্য প্রজন্ম এবং চরিত্র আন্দোলন বাস্তবায়ন করেছি। আমরা একটি অস্ত্রের মডেলও যোগ করেছি, গুলি চালানোর সময় এবং নিষ্ক্রিয় অবস্থায় রিকোয়েল অ্যানিমেশন। পরবর্তী অংশে আমরা নতুন কার্যকারিতা যোগ করে আমাদের গেমকে পরিমার্জন করতে থাকব।
এছাড়াও এখানে প্রকাশিত.