PageSourceSearch

https://accelagent.github.io/dist/demo/js/bodies/swimmers/fish_body.js

js accelagent.github.io collected 2026-10-03 08:32:35 UTC 9,176 bytes, 248 lines download raw bytes

1// Head
2HULL_POLYGON = [
3    [-20, +12], [+6, +12],
4    [+15, +4], [+15, -4],
5    [+6, -12], [-20, -12]
6];
7
8BODY_P1 = [
9    [-8, +9], [+8, +12],
10    [+8, -12], [-8, -9]
11];
12
13BODY_P2 = [
14    [-8, +4], [+8, +9],
15    [+8, -9], [-8, -4]
16];
17
18// Tail
19BODY_P3 = [
20    [-4, +2], [+4, +4],
21    [+4, -4], [-4, -2]
22];
23
24FIN = [
25    [-1, -10], [-1, +10],
26    [+1, +10], [+1, -10]
27];
28
29HULL_BOTTOM_WIDTH = 35;
30const SPEED = 6;
31
32/**
33 * @classdesc Fish morphology.
34 */
35class FishBody extends SwimmerAbstractBody {
36    /**
37     * @constructor
38     * @param scale {number} - Scale of the environment
39     * @param motors_torque {number}
40     * @param density {number} - Density of the agent's body.
41     * @param nb_steps_outside_water {number}
42     */
43    constructor(scale, motors_torque=80, density, nb_steps_outside_water=600) {
44        super(scale, motors_torque, density, nb_steps_outside_water);
45        this.TORQUE_PENALTY = 0.00035;
46
47        this.AGENT_WIDTH = HULL_BOTTOM_WIDTH / this.SCALE;
48        this.AGENT_HEIGHT = 18 / this.SCALE;
49        this.AGENT_CENTER_HEIGHT = 9 / this.SCALE;
50
51        this.remove_reward_on_head_angle = true;
52
53        this.fins = [];
54        this.tail = null;
55    }
56
57    draw(world, init_x, init_y){
58
59        let vertices;
60        let rjd;
61        let joint_motor;
62
63        // HULL
64        let hull_fd = new b2.FixtureDef();
65        hull_fd.shape = new b2.PolygonShape();
66        vertices = [];
67        for(let vertex of HULL_POLYGON){
68            vertices.push(new b2.Vec2(vertex[0] / this.SCALE, vertex[1] / this.SCALE));
69        }
70        hull_fd.shape.Set(vertices, HULL_POLYGON.length);
71        hull_fd.density = this.DENSITY;
72        hull_fd.friction = 0.1;
73        hull_fd.filter.categoryBits = 0x20;
74        hull_fd.filter.maskBits = 0x000F; // 0.99 bouncy
75
76        let hull_bd = new b2.BodyDef();
77        hull_bd.type = b2.Body.b2_dynamicBody;
78        hull_bd.position.Set(init_x, init_y);
79        let hull = world.CreateBody(hull_bd);
80        hull.CreateFixture(hull_fd);
81        hull.color1 = "#806682"; // [0.5, 0.4, 0.9]
82        hull.color2 = "#4D4D80";
83        hull.SetUserData(new CustomBodyUserData(true, false, "head"));
84        this.body_parts.push(hull);
85        this.reference_head_object = hull;
86
87        // BODY_P1
88        let body_p1_x = init_x - 35 / 2 / this.SCALE - 16 / 2 / this.SCALE;
89        let body_p1_fd = new b2.FixtureDef();
90        body_p1_fd.shape = new b2.PolygonShape();
91        vertices = [];
92        for(let vertex of BODY_P1){
93            vertices.push(new b2.Vec2(vertex[0] / this.SCALE, vertex[1] / this.SCALE));
94        }
95        body_p1_fd.shape.Set(vertices, BODY_P1.length);
96        body_p1_fd.density = this.DENSITY;
97        body_p1_fd.restitution = 0.0;
98        body_p1_fd.filter.categoryBits = 0x20;
99        body_p1_fd.filter.maskBits = 0x000F; // 0.99 bouncy
100
101        let body_p1_bd = new b2.BodyDef();
102        body_p1_bd.type = b2.Body.b2_dynamicBody;
103        body_p1_bd.position.Set(body_p1_x, init_y);
104        let body_p1 = world.CreateBody(body_p1_bd);
105        body_p1.CreateFixture(body_p1_fd);
106        body_p1.color1 = "#806682"; // [0.5, 0.4, 0.9]
107        body_p1.color2 = "#4D4D80";
108        body_p1.SetUserData(new CustomBodyUserData(true, false, "body"));
109        this.body_parts.push(body_p1);
110
111        // Revolute joint between HULL and BODY_P1
112        rjd = new b2.RevoluteJointDef();
113        rjd.Initialize(hull, body_p1, new b2.Vec2(init_x - 35 / 2 / this.SCALE, init_y));
114        rjd.enableMotor = true;
115        rjd.enableLimit = true;
116        rjd.maxMotorTorque = this.MOTORS_TORQUE;
117        rjd.motorSpeed = 1;
118        rjd.lowerAngle = -0.1 * Math.PI;
119        rjd.upperAngle = 0.2 * Math.PI;
120        joint_motor = world.CreateJoint(rjd);
121        joint_motor.SetUserData(new CustomMotorUserData("neck", SPEED, true, 0.0, body_p1));
122        this.motors.push(joint_motor);
123
124        // BODY_P2
125        let body_p2_x = body_p1_x - 16 / 2 / this.SCALE - 16 / 2 / this.SCALE;
126        let body_p2_fd = new b2.FixtureDef();
127        body_p2_fd.shape = new b2.PolygonShape();
128        vertices = [];
129        for(let vertex of BODY_P2){
130            vertices.push(new b2.Vec2(vertex[0] / this.SCALE, vertex[1] / this.SCALE));
131        }
132        body_p2_fd.shape.Set(vertices, BODY_P2.length);
133        body_p2_fd.density = this.DENSITY;
134        body_p2_fd.restitution = 0.0;
135        body_p2_fd.filter.categoryBits = 0x20;
136        body_p2_fd.filter.maskBits = 0x000F;
137
138        let body_p2_bd = new b2.BodyDef();
139        body_p2_bd.type = b2.Body.b2_dynamicBody;
140        body_p2_bd.position.Set(body_p2_x, init_y);
141        let body_p2 = world.CreateBody(body_p2_bd);
142        body_p2.CreateFixture(body_p2_fd);
143        body_p2.color1 = "#806682"; // [0.5, 0.4, 0.9]
144        body_p2.color2 = "#4D4D80";
145        body_p2.SetUserData(new CustomBodyUserData(true, false, "body"));
146        this.body_parts.push(body_p2);
147
148        // Revolute joint between BODY_P1 and BODY_P2
149        rjd = new b2.RevoluteJointDef();
150        rjd.Initialize(body_p1, body_p2, new b2.Vec2(body_p1_x - 16 / 2 / this.SCALE, init_y));
151        rjd.enableMotor = true;
152        rjd.enableLimit = true;
153        rjd.maxMotorTorque = this.MOTORS_TORQUE;
154        rjd.motorSpeed = 1;
155        rjd.lowerAngle = -0.15 * Math.PI;
156        rjd.upperAngle = 0.15 * Math.PI;
157        joint_motor = world.CreateJoint(rjd);
158        joint_motor.SetUserData(new CustomMotorUserData("hip", SPEED, true, 0.0, body_p2));
159        this.motors.push(joint_motor);
160
161        // BODY_P3 - TAIL
162        let body_p3_x = body_p2_x - 16 / 2 / this.SCALE - 8 / 2 / this.SCALE;
163        let body_p3_fd = new b2.FixtureDef();
164        body_p3_fd.shape = new b2.PolygonShape();
165        vertices = [];
166        for(let vertex of BODY_P3){
167            vertices.push(new b2.Vec2(vertex[0] / this.SCALE, vertex[1] / this.SCALE));
168        }
169        body_p3_fd.shape.Set(vertices, BODY_P3.length);
170        body_p3_fd.density = this.DENSITY;
171        body_p3_fd.restitution = 0.0;
172        body_p3_fd.filter.categoryBits = 0x20;
173        body_p3_fd.filter.maskBits = 0x000F;
174
175        let body_p3_bd = new b2.BodyDef();
176        body_p3_bd.type = b2.Body.b2_dynamicBody;
177        body_p3_bd.position.Set(body_p3_x, init_y);
178        let body_p3 = world.CreateBody(body_p3_bd);
179        body_p3.CreateFixture(body_p3_fd);
180        body_p3.color1 = "#806682"; // [0.5, 0.4, 0.9]
181        body_p3.color2 = "#4D4D80";
182        body_p3.SetUserData(new CustomBodyUserData(true, false, "body"));
183        this.body_parts.push(body_p3);
184        this.tail = body_p3;
185
186        // Revolute joint between BODY_P2 and BODY_P3
187        rjd = new b2.RevoluteJointDef();
188        rjd.Initialize(body_p2, body_p3, new b2.Vec2(body_p2_x - 16 / 2 / this.SCALE, init_y));
189        rjd.enableMotor = true;
190        rjd.enableLimit = true;
191        rjd.maxMotorTorque = this.MOTORS_TORQUE;
192        rjd.motorSpeed = 1;
193        rjd.lowerAngle = -0.3 * Math.PI;
194        rjd.upperAngle = 0.3 * Math.PI;
195        joint_motor = world.CreateJoint(rjd);
196        joint_motor.SetUserData(new CustomMotorUserData("knee", SPEED, true, 0.0, body_p3));
197        this.motors.push(joint_motor);
198
199        // FINS
200        let fin_fd = new b2.FixtureDef();
201        fin_fd.shape = new b2.PolygonShape();
202        vertices = [];
203        for(let vertex of FIN){
204            vertices.push(new b2.Vec2(vertex[0] / this.SCALE, vertex[1] / this.SCALE));
205        }
206        fin_fd.shape.Set(vertices, FIN.length);
207        fin_fd.density = this.DENSITY;
208        fin_fd.restitution = 0.0;
209        fin_fd.filter.categoryBits = 0x20;
210        fin_fd.filter.maskBits = 0x000F;
211
212        let fin_positions = [
213            [init_x, init_y - 22 / 2 / this.SCALE + 0.2],
214        ];
215        let fin_angle = -0.2 * Math.PI;
216        let middle_fin_x_distance = Math.sin(fin_angle) * 20 / 2 / this.SCALE;
217        let middle_fin_y_distance = Math.cos(fin_angle) * 20 / 2 / this.SCALE;
218
219        for(let fin_pos of fin_positions){
220            let current_fin_x = fin_pos[0] + middle_fin_x_distance;
221            let current_fin_y = fin_pos[1] - middle_fin_y_distance;
222
223            let fin_bd = new b2.BodyDef();
224            fin_bd.type = b2.Body.b2_dynamicBody;
225            fin_bd.position.Set(current_fin_x, current_fin_y);
226            let fin = world.CreateBody(fin_bd);
227            fin.CreateFixture(fin_fd);
228            fin.color1 = "#806682"; // [0.5, 0.4, 0.9]
229            fin.color2 = "#4D4D80";
230            fin.SetUserData(new CustomBodyUserData(true, false, "fin"));
231            this.body_parts.push(fin);
232            this.fins.push(fin);
233
234            // Revolute joint between HULL and FIN
235            rjd = new b2.RevoluteJointDef();
236            rjd.Initialize(hull, fin, new b2.Vec2(fin_pos[0], fin_pos[1]));
237            rjd.enableMotor = true;
238            rjd.enableLimit = true;
239            rjd.maxMotorTorque = this.MOTORS_TORQUE;
240            rjd.motorSpeed = 1;
241            rjd.lowerAngle = -0.3 * Math.PI;
242            rjd.upperAngle = 0.2 * Math.PI;
243            joint_motor = world.CreateJoint(rjd);
244            joint_motor.SetUserData(new CustomMotorUserData("shoulder", SPEED, true, 0.0, fin));
245            this.motors.push(joint_motor);
246        }
247    }
248}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.