আধুনিক ওয়েব বিকাশে, ক্লাসিক এবং ওয়েব অ্যাপ্লিকেশনগুলির মধ্যে সীমানা প্রতিদিন ঝাপসা হয়ে আসছে। আজ আমরা ব্রাউজারে শুধুমাত্র ইন্টারেক্টিভ ওয়েবসাইট নয়, পূর্ণাঙ্গ গেমও তৈরি করতে পারি। এটি সম্ভব করে তোলে এমন একটি টুল হল লাইব্রেরি - রিঅ্যাক্ট প্রযুক্তি ব্যবহার করে এর উপর ভিত্তি করে 3D গ্রাফিক্স তৈরি করার একটি শক্তিশালী টুল।
রিঅ্যাক্ট থ্রি ফাইবার হল Three.js- এর উপর একটি মোড়ক যা ওয়েবে 3D গ্রাফিক্স তৈরি করতে React এর গঠন এবং নীতি ব্যবহার করে। এই স্ট্যাকটি ডেভেলপারদের রিঅ্যাক্ট- এর সুবিধা এবং নমনীয়তার সাথে Three.js- এর শক্তিকে একত্রিত করতে দেয়, একটি অ্যাপ্লিকেশন তৈরির প্রক্রিয়াকে আরও স্বজ্ঞাত এবং সংগঠিত করে।
রিঅ্যাক্ট থ্রি ফাইবার- এর কেন্দ্রে এই ধারণা যে আপনি একটি দৃশ্যে যা কিছু তৈরি করেন তা হল একটি প্রতিক্রিয়া উপাদান। এটি বিকাশকারীদের পরিচিত নিদর্শন এবং পদ্ধতিগুলি প্রয়োগ করতে দেয়।
রিঅ্যাক্ট থ্রি ফাইবারের অন্যতম প্রধান সুবিধা হল রিঅ্যাক্ট ইকোসিস্টেমের সাথে এর একীকরণের সহজতা। এই লাইব্রেরি ব্যবহার করার সময় অন্য যেকোন রিঅ্যাক্ট টুল এখনও সহজেই ইন্টিগ্রেট করা যায়।
ওয়েব-গেমডেভ সাম্প্রতিক বছরগুলিতে বড় পরিবর্তনের মধ্য দিয়ে গেছে, সাধারণ 2D গেমগুলি থেকে ডেস্কটপ অ্যাপ্লিকেশনগুলির সাথে তুলনীয় জটিল 3D প্রকল্পগুলিতে বিবর্তিত হয়েছে। জনপ্রিয়তা এবং ক্ষমতার এই বৃদ্ধি ওয়েব-গেমডেভকে এমন একটি ক্ষেত্র করে তোলে যা উপেক্ষা করা যায় না।
আধুনিক ব্রাউজারগুলি অনেক দূর এগিয়েছে, জটিল অ্যাপ্লিকেশন এবং গেমগুলি চালানোর জন্য মোটামুটি সহজ ওয়েব ব্রাউজিং সরঞ্জাম থেকে শক্তিশালী প্ল্যাটফর্মে বিবর্তিত হয়েছে। ক্রোম , ফায়ারফক্স , এজ এবং অন্যান্যগুলির মতো প্রধান ব্রাউজারগুলিকে ক্রমাগত অপ্টিমাইজ করা হচ্ছে এবং উন্নত কর্মক্ষমতা নিশ্চিত করার জন্য উন্নত করা হচ্ছে, যা তাদের জটিল অ্যাপ্লিকেশনগুলি বিকাশের জন্য একটি আদর্শ প্ল্যাটফর্ম করে তুলেছে৷
ব্রাউজার-ভিত্তিক গেমিং-এর বিকাশে ইন্ধন জোগায় এমন একটি মূল টুল হল । এই মানটি বিকাশকারীদের হার্ডওয়্যার গ্রাফিক্স ত্বরণ ব্যবহার করার অনুমতি দেয়, যা 3D গেমগুলির কার্যকারিতা উল্লেখযোগ্যভাবে উন্নত করে। অন্যান্য webAPI-এর সাথে একত্রে, WebGL ব্রাউজারে সরাসরি চিত্তাকর্ষক ওয়েব অ্যাপ্লিকেশন তৈরি করার জন্য নতুন সম্ভাবনা উন্মুক্ত করে।
প্রথমত, আমাদের একটি প্রতিক্রিয়া প্রকল্প টেমপ্লেট প্রয়োজন হবে। তাহলে এর ইন্সটল করে শুরু করা যাক।
npm create vite@latest
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 ফাংশন যোগ করি।
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> ); }
আগের একক কিউব মুছে দিয়ে অ্যাপ কম্পোনেন্টে তৈরি করা কিউবস কম্পোনেন্ট যোগ করা যাক।
বিন্যাস পেতে আমাদের দৃশ্যে মডেল আমদানি করতে হবে, আমাদের 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 এর মাধ্যমে কিছু নতুন রাজ্য যোগ করি।