-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathconstants.js
More file actions
295 lines (273 loc) · 11 KB
/
constants.js
File metadata and controls
295 lines (273 loc) · 11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
import * as THREE from 'three';
// Game Constants
export const GAME_CONFIG = {
INITIAL_SPEED: 0.13,
SPEED_INCREMENT: 0.000050,
GRAVITY: -0.025,
INITIAL_JUMP_VELOCITY: 0.28,
DOUBLE_JUMP_VELOCITY: 0.45,
GROUND_HEIGHT: 0.5,
PLAYER_VISUAL_OFFSET: -0.35, // Offset to align GLB model visual center with collision box
CAMERA_FOLLOW_SPEED: 0.1,
LANE_SWITCH_SPEED: 0.35,
DEBUG_COLLISIONS: false // Set to true to visualize player collision box
};
export const COUNTDOWN_CONFIG = {
DURATION: 3000, // 3 seconds
NUMBERS: [3, 2, 1, 'GO!'],
ANIMATION_DURATION: 800, // Duration for each number animation
READY_ANIMATION_DURATION: 1500, // Duration for character ready animation
SKIP_ENABLED: true
};
export const LANES = {
POSITIONS: [-2, 0, 2],
COUNT: 3,
LEFT: 0,
CENTER: 1,
RIGHT: 2
};
export const COLORS = {
PLAYER: {
DEFAULT: 0xff0000,
INVINCIBLE: 0x00ff00,
FLYING: 0x888888,
SOLAR_BOOST: 0xffff00,
WIND_POWER: 0xaaffaa,
WATER_SLIDE: 0x00aaff
},
OBSTACLES: {
POTHOLE: 0x333333,
CONSTRUCTION_BARRIER: 0xff4444,
CONE: 0xff8800,
RUBBLE: 0x808080,
ELECTRIC_LINE: 0xffff00
},
COLLECTABLES: {
BLUEPRINT: 0x0000ff,
WATER_DROP: 0x00ffff,
ENERGY_CELL: 0xffff00,
HARD_HAT: 0xffa500,
HELICOPTER: 0x444444,
SOLAR_POWER: 0xffff00,
WIND_POWER: 0xaaffaa,
WATER_PIPELINE: 0x0088ff,
AERIAL_STAR: 0xffdd00,
SOLAR_ORB: 0xffcc33 // New: Solar energy collectible
},
ENVIRONMENT: {
SKY_WARM: 0xFF6B35, // Vibrant African sunset orange
SKY: 0x87CEEB,
ROAD_BASE: '#404040',
ROAD_TEXTURE: '#505050',
ROAD_MARKINGS: '#FFD700', // Gold markings for African flair
TREE_TRUNK: 0x8B4513, // Brown
TREE_FOLIAGE: 0x228B22, // Forest Green
PAVEMENT: 0xFFD700, // Golden pavement for vibrant look
GREENERY: 0x32CD32, // More vibrant green
CONSTRUCTION_GROUND: 0xCD853F, // Richer earth tone
// New African-inspired surface colors
MARKET_SURFACE: 0xFF6347, // Vibrant terracotta
PLAZA_SURFACE: 0xFFD700, // Golden plaza
CULTURAL_SURFACE: 0x663399, // Rich purple
RESIDENTIAL_SURFACE: 0xDEB887 // Warm beige
},
BUILDINGS: {
INFRASTRUCTURE: 0x0047AB, // Bold blue for infrastructure
// Enhanced African-inspired building colors
MODERN_TOWER: [0x0047AB, 0x1E90FF, 0x4169E1], // Bold blues
RESIDENTIAL_WARM: [0xFF6347, 0xCD853F, 0xDEB887], // Warm earth tones
COMMERCIAL_VIBRANT: [0xFFD700, 0xFFA500, 0xFF8C00], // Golden yellows
CULTURAL_RICH: [0x663399, 0x9966CC, 0xBA55D3], // Rich purples
MIXED_USE: [0x228B22, 0x32CD32, 0x006400], // Natural greens
TRADITIONAL: [0xCD853F, 0xD2691E, 0xA0522D] // Rich terracotta
}
};
export const SPAWN_CONFIG = {
OBSTACLE_MIN_DISTANCE: 12,
OBSTACLE_SAFE_DISTANCE_MULTIPLIER: 1.5,
BUILDING_INTERVAL: { MIN: 8000, MAX: 15000 }, // Restored building density
BUILDING_OFFSET_FROM_ROAD: 20,
BUILDING_SPAWN_DISTANCE_AHEAD: 100,
BUILDING_CLUSTER_SIZE: { MIN: 1, MAX: 1 },
BUILDING_CLUSTER_SPREAD: 0,
STREET_DECORATION_INTERVAL: { MIN: 2000, MAX: 4000 }, // Restored tree spawning
STREET_DECORATION_CHANCE: 0.3, // Restored tree chance
STREET_DECORATION_OFFSET: 2.5,
SIDE_AREA_LENGTH: 25,
SIDE_AREA_WIDTH: 30,
SIDE_AREA_SPAWN_TRIGGER_OFFSET: 180,
SIDE_AREA_DESPAWN_OFFSET: 25,
COLLECTABLE_INTERVAL: { MIN: 2000, MAX: 5000 }, // Restored collectable frequency
OBSTACLE_INTERVAL: { MIN: 1800, MAX: 3500 }, // Restored obstacle frequency
AERIAL_SPAWN_CHANCE: 0.02,
SOLAR_ORB_SPAWN_CHANCE: 0.03, // Slightly higher chance than aerial stars
OBSTACLE_DYNAMIC_INTERVAL: {
ENABLED: true,
MIN_CLAMP: 700, // Absolute minimum spawn interval (ms)
MAX_CLAMP_MIN_OFFSET: 300, // Ensures MAX_CLAMP is always at least MIN_CLAMP + this offset
// How much the interval (both min and max of the range) decreases per unit of game speed.
// e.g., if gameSpeed is 0.2 and sensitivity is 5000, reduction is 0.2 * 5000 = 1000ms.
SPEED_SENSITIVITY: 6000
}
};
export const POWER_UP_DURATIONS = {
INVINCIBILITY: 5000, // 5 seconds
HELICOPTER: 10000, // 10 seconds
SOLAR_BOOST: 8000, // 8 seconds
WIND_POWER: 15000, // 15 seconds
WATER_SLIDE: 12000 // 12 seconds
};
export const SCORING = {
OBSTACLE_PASSED: 15,
BLUEPRINT: 50,
WATER_DROP: 20,
ENERGY_CELL: 30,
POWER_UP: 100,
AERIAL_STAR: 150,
SOLAR_ORB: 120, // New: Slightly less than aerial stars since they're easier to get
BASE_RATE: 0.15,
SOLAR_BOOST_RATE: 0.2
};
export const PHYSICS = {
MAGNET_RADIUS: 5,
MAGNET_PULL_SPEED: 0.2,
FLYING_HEIGHT: 1.0, // Character flies around Y=1.0 based on console logs
COLLISION_SHRINK: 0.1, // General shrink for X and Z axes
COLLISION_SHRINK_Y: 0.0, // Specific shrink for Y axis (bottom of the player) - Set to 0 to minimize lifting
// High-speed collision detection settings
HIGH_SPEED_THRESHOLD: 0.15, // Speed at which to use enhanced collision detection
COLLECTABLE_EXPANSION_BASE: 0.3, // Base expansion for collectable collection radius
COLLECTABLE_SPEED_EXPANSION: 2, // How much collection radius grows with speed
MAGNET_EXPANSION_BONUS: 0.5, // Additional expansion when magnet effect is active
SAFE_SPAWN_DISTANCE_BASE: 3, // Base safe distance for spawning objects
SAFE_SPAWN_DISTANCE_SPEED_MULTIPLIER: 10, // Distance multiplier based on speed
MAX_COLLISION_BOX_EXPANSION: 1.2 // Maximum factor for collision box expansion
};
export const OBSTACLE_TYPES = {
'pothole': {
geometry: () => new THREE.CylinderGeometry(0.5, 0.5, 0.1, 32),
color: COLORS.OBSTACLES.POTHOLE,
yPos: 0.05,
description: 'Road damage that needs repair'
},
'constructionBarrier': {
geometry: () => new THREE.BoxGeometry(1.5, 1, 0.3),
color: COLORS.OBSTACLES.CONSTRUCTION_BARRIER,
yPos: 0.5,
description: 'Construction zone barrier'
},
'cone': {
geometry: () => new THREE.ConeGeometry(0.3, 0.8, 32),
color: COLORS.OBSTACLES.CONE,
yPos: 0.4,
description: 'Traffic cone marking road work'
},
'rubble': {
geometry: () => new THREE.BoxGeometry(0.8, 0.4, 0.8),
color: COLORS.OBSTACLES.RUBBLE,
yPos: 0.2,
description: 'Construction debris'
},
'electricLine': {
geometry: () => {
// Create a group to hold the poles and wire
const group = new THREE.Group();
// Helper function to create a realistic power pole
const createPowerPole = (xPosition) => {
const poleGroup = new THREE.Group();
// Main pole (concrete/wood texture)
const mainPole = new THREE.Mesh(
new THREE.CylinderGeometry(0.08, 0.12, 3.0, 8),
new THREE.MeshStandardMaterial({
color: 0x696969, // Dark gray for concrete
roughness: 0.8
})
);
mainPole.position.set(0, 1.5, 0);
poleGroup.add(mainPole);
// Crossbeam (horizontal support)
const crossbeam = new THREE.Mesh(
new THREE.BoxGeometry(1.2, 0.08, 0.08),
new THREE.MeshStandardMaterial({
color: 0x8B4513, // Brown wood
roughness: 0.9
})
);
crossbeam.position.set(0, 1.9, 0);
poleGroup.add(crossbeam);
// Insulators (ceramic-like)
for (let i = -0.4; i <= 0.4; i += 0.4) {
const insulator = new THREE.Mesh(
new THREE.CylinderGeometry(0.03, 0.05, 0.15, 6),
new THREE.MeshStandardMaterial({
color: 0xF5F5DC, // Beige ceramic
roughness: 0.3
})
);
insulator.position.set(i, 2.0, 0);
poleGroup.add(insulator);
}
// Position the entire pole
poleGroup.position.set(xPosition, 0, 0);
return poleGroup;
};
// Create left and right power poles
const leftPole = createPowerPole(-4.5);
const rightPole = createPowerPole(4.5);
group.add(leftPole);
group.add(rightPole);
// Create sagging power line using curve
const curve = new THREE.QuadraticBezierCurve3(
new THREE.Vector3(-4.5, 2.0, 0), // Start at left pole attachment
new THREE.Vector3(0, 1.0, 0), // Sag point in middle (slightly below player height)
new THREE.Vector3(4.5, 2.0, 0) // End at right pole attachment
);
// Create wire geometry from curve
const wireGeometry = new THREE.TubeGeometry(curve, 20, 0.015, 8, false);
const wire = new THREE.Mesh(
wireGeometry,
new THREE.MeshStandardMaterial({
color: 0x2F2F2F, // Dark metallic wire
metalness: 0.8,
roughness: 0.2
})
);
group.add(wire);
// Add warning signs on poles
const createWarningSign = (xPos) => {
const sign = new THREE.Mesh(
new THREE.BoxGeometry(0.3, 0.2, 0.02),
new THREE.MeshStandardMaterial({
color: 0xFFFF00, // Yellow warning
roughness: 0.1
})
);
sign.position.set(xPos, 1.0, 0.1);
return sign;
};
group.add(createWarningSign(-4.5));
group.add(createWarningSign(4.5));
return group;
},
color: COLORS.OBSTACLES.ELECTRIC_LINE,
yPos: 0, // Group positioning handled in geometry
description: 'Loose electric line - slide or jump to avoid'
}
};
export const COLLECTABLE_SPAWN_WEIGHTS = {
REGULAR: ['blueprint', 'waterDrop', 'energyCell'],
// New weighted array for power-ups to control rarity. This will be used
// as a "deck" to ensure all power-ups spawn.
// Common: windPower (4 instances)
// Uncommon: hardHat (2), waterPipeline (2)
// Rare: helicopter (1), solarPower (1)
POWER_UPS: [
'windPower', 'windPower', 'windPower', 'windPower',
'hardHat', 'hardHat',
'waterPipeline', 'waterPipeline',
'helicopter',
'solarPower'
],
REGULAR_WEIGHT: 6,
POWER_UP_WEIGHT: 1
};