Spaces:
Sleeping
Sleeping
Update static/tribalStage.js
Browse files- static/tribalStage.js +86 -67
static/tribalStage.js
CHANGED
@@ -1,30 +1,84 @@
|
|
1 |
class TribalStage extends GameStage {
|
2 |
-
constructor(
|
3 |
-
super(
|
4 |
this.creatures = [];
|
5 |
this.huts = [];
|
6 |
this.rivalTribes = [];
|
7 |
-
|
8 |
-
|
9 |
-
this.
|
10 |
-
|
11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
}
|
13 |
|
14 |
init() {
|
15 |
-
this.
|
16 |
-
this.spawnRivalTribe(600, 100); // Rival tribe
|
17 |
-
this.render();
|
18 |
}
|
19 |
|
20 |
-
spawnCreature(x,
|
21 |
-
this.
|
|
|
|
|
|
|
22 |
this.population = this.creatures.length;
|
23 |
this.updateUI();
|
24 |
}
|
25 |
|
26 |
-
spawnRivalTribe(x,
|
27 |
-
this.
|
|
|
|
|
|
|
28 |
}
|
29 |
|
30 |
gatherFood() {
|
@@ -35,9 +89,12 @@ class TribalStage extends GameStage {
|
|
35 |
buildHut() {
|
36 |
if (this.resources.food >= 20 && this.huts.length < 5) {
|
37 |
this.resources.food -= 20;
|
38 |
-
|
|
|
|
|
|
|
39 |
this.maxPopulation += 2;
|
40 |
-
this.spawnCreature(
|
41 |
}
|
42 |
this.updateUI();
|
43 |
}
|
@@ -46,6 +103,7 @@ class TribalStage extends GameStage {
|
|
46 |
if (this.rivalTribes.length > 0 && this.creatures.length > 1) {
|
47 |
this.rivalTribes[0].members -= 1;
|
48 |
if (this.rivalTribes[0].members <= 0) {
|
|
|
49 |
this.rivalTribes.shift();
|
50 |
this.relations = "Victorious";
|
51 |
} else {
|
@@ -66,69 +124,30 @@ class TribalStage extends GameStage {
|
|
66 |
|
67 |
applyCreatureChanges() {
|
68 |
const color = document.getElementById("creatureColor").value;
|
69 |
-
const
|
70 |
this.creatures.forEach(c => {
|
71 |
-
c.
|
72 |
-
|
|
|
|
|
|
|
|
|
73 |
});
|
74 |
toggleEditor(); // Hide editor after applying
|
75 |
}
|
76 |
|
77 |
update() {
|
78 |
this.creatures.forEach(creature => {
|
79 |
-
creature.x += (Math.random() - 0.5) * creature.speed;
|
80 |
-
creature.
|
81 |
-
creature.x = Math.max(
|
82 |
-
creature.
|
83 |
});
|
84 |
}
|
85 |
-
|
86 |
-
render() {
|
87 |
-
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
88 |
-
|
89 |
-
// Draw grass background
|
90 |
-
for (let x = 0; x < this.canvas.width; x += 32) {
|
91 |
-
for (let y = 0; y < this.canvas.height; y += 32) {
|
92 |
-
if (this.grassImg.complete) this.ctx.drawImage(this.grassImg, x, y, 32, 32);
|
93 |
-
}
|
94 |
-
}
|
95 |
-
|
96 |
-
// Draw huts
|
97 |
-
this.huts.forEach(hut => {
|
98 |
-
if (this.hutImg.complete) this.ctx.drawImage(this.hutImg, hut.x, hut.y, 48, 48);
|
99 |
-
});
|
100 |
-
|
101 |
-
// Draw firepits (optional decoration)
|
102 |
-
this.huts.forEach((hut, i) => {
|
103 |
-
if (i % 2 === 0 && this.firepitImg.complete) {
|
104 |
-
this.ctx.drawImage(this.firepitImg, hut.x + 20, hut.y + 20, 32, 32);
|
105 |
-
}
|
106 |
-
});
|
107 |
-
|
108 |
-
// Draw rival tribes
|
109 |
-
this.rivalTribes.forEach(tribe => {
|
110 |
-
if (this.rivalImg.complete) this.ctx.drawImage(this.rivalImg, tribe.x, tribe.y, 32, 32);
|
111 |
-
this.ctx.fillStyle = tribe.hostile ? "red" : "green";
|
112 |
-
this.ctx.fillText(`Members: ${tribe.members}`, tribe.x, tribe.y - 10);
|
113 |
-
});
|
114 |
-
|
115 |
-
// Draw creatures with custom color/size
|
116 |
-
this.creatures.forEach(creature => {
|
117 |
-
if (this.creatureImg.complete) {
|
118 |
-
this.ctx.drawImage(this.creatureImg, creature.x, creature.y, creature.size, creature.size);
|
119 |
-
} else {
|
120 |
-
this.ctx.fillStyle = creature.color;
|
121 |
-
this.ctx.fillRect(creature.x, creature.y, creature.size, creature.size);
|
122 |
-
}
|
123 |
-
});
|
124 |
-
|
125 |
-
this.update();
|
126 |
-
requestAnimationFrame(() => this.render());
|
127 |
-
}
|
128 |
}
|
129 |
|
130 |
let game;
|
131 |
document.addEventListener("DOMContentLoaded", () => {
|
132 |
-
game = new TribalStage(
|
133 |
game.init();
|
134 |
});
|
|
|
1 |
class TribalStage extends GameStage {
|
2 |
+
constructor() {
|
3 |
+
super();
|
4 |
this.creatures = [];
|
5 |
this.huts = [];
|
6 |
this.rivalTribes = [];
|
7 |
+
|
8 |
+
// Load 3D models via URLs
|
9 |
+
this.loadModels();
|
10 |
+
}
|
11 |
+
|
12 |
+
loadModels() {
|
13 |
+
const loader = new THREE.GLTFLoader();
|
14 |
+
const textureLoader = new THREE.TextureLoader();
|
15 |
+
|
16 |
+
// Grass (terrain texture)
|
17 |
+
textureLoader.load(
|
18 |
+
"https://cdn.pixabay.com/photo/2013/07/12/18/40/grass-150056_1280.png",
|
19 |
+
(texture) => {
|
20 |
+
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
|
21 |
+
texture.repeat.set(10, 10); // Tile the texture
|
22 |
+
this.ground.material = new THREE.MeshBasicMaterial({ map: texture });
|
23 |
+
},
|
24 |
+
undefined,
|
25 |
+
(error) => console.error("Grass texture load error:", error)
|
26 |
+
);
|
27 |
+
|
28 |
+
// Tribal Creature (Player)
|
29 |
+
loader.load(
|
30 |
+
"https://polyhaven.com/a/tribal_warrior", // Simplified URL; download GLTF from Poly Haven
|
31 |
+
(gltf) => {
|
32 |
+
this.creatureModel = gltf.scene;
|
33 |
+
this.creatureModel.scale.set(0.5, 0.5, 0.5); // Scale down for game size
|
34 |
+
this.spawnCreature(0, 0);
|
35 |
+
},
|
36 |
+
undefined,
|
37 |
+
(error) => console.error("Creature load error:", error)
|
38 |
+
);
|
39 |
+
|
40 |
+
// Hut
|
41 |
+
loader.load(
|
42 |
+
"https://polyhaven.com/a/hut", // Download GLTF from Poly Haven
|
43 |
+
(gltf) => {
|
44 |
+
this.hutModel = gltf.scene;
|
45 |
+
this.hutModel.scale.set(0.5, 0.5, 0.5);
|
46 |
+
},
|
47 |
+
undefined,
|
48 |
+
(error) => console.error("Hut load error:", error)
|
49 |
+
);
|
50 |
+
|
51 |
+
// Rival Tribe
|
52 |
+
loader.load(
|
53 |
+
"https://sketchfab.com/3d-models/tribal-warrior-7b9f9f7e2b7b4a2a8f1c9d0e", // Download GLTF, free version
|
54 |
+
(gltf) => {
|
55 |
+
this.rivalModel = gltf.scene;
|
56 |
+
this.rivalModel.scale.set(0.5, 0.5, 0.5);
|
57 |
+
this.spawnRivalTribe(5, 5);
|
58 |
+
},
|
59 |
+
undefined,
|
60 |
+
(error) => console.error("Rival load error:", error)
|
61 |
+
);
|
62 |
}
|
63 |
|
64 |
init() {
|
65 |
+
this.animate();
|
|
|
|
|
66 |
}
|
67 |
|
68 |
+
spawnCreature(x, z) {
|
69 |
+
const creature = this.creatureModel.clone();
|
70 |
+
creature.position.set(x, 0, z);
|
71 |
+
this.scene.add(creature);
|
72 |
+
this.creatures.push({ model: creature, speed: 0.05 });
|
73 |
this.population = this.creatures.length;
|
74 |
this.updateUI();
|
75 |
}
|
76 |
|
77 |
+
spawnRivalTribe(x, z) {
|
78 |
+
const tribe = this.rivalModel.clone();
|
79 |
+
tribe.position.set(x, 0, z);
|
80 |
+
this.scene.add(tribe);
|
81 |
+
this.rivalTribes.push({ model: tribe, members: 3, hostile: true });
|
82 |
}
|
83 |
|
84 |
gatherFood() {
|
|
|
89 |
buildHut() {
|
90 |
if (this.resources.food >= 20 && this.huts.length < 5) {
|
91 |
this.resources.food -= 20;
|
92 |
+
const hut = this.hutModel.clone();
|
93 |
+
hut.position.set(-5 + this.huts.length, 0, 0);
|
94 |
+
this.scene.add(hut);
|
95 |
+
this.huts.push(hut);
|
96 |
this.maxPopulation += 2;
|
97 |
+
this.spawnCreature(0, 0);
|
98 |
}
|
99 |
this.updateUI();
|
100 |
}
|
|
|
103 |
if (this.rivalTribes.length > 0 && this.creatures.length > 1) {
|
104 |
this.rivalTribes[0].members -= 1;
|
105 |
if (this.rivalTribes[0].members <= 0) {
|
106 |
+
this.scene.remove(this.rivalTribes[0].model);
|
107 |
this.rivalTribes.shift();
|
108 |
this.relations = "Victorious";
|
109 |
} else {
|
|
|
124 |
|
125 |
applyCreatureChanges() {
|
126 |
const color = document.getElementById("creatureColor").value;
|
127 |
+
const scale = parseFloat(document.getElementById("creatureSize").value);
|
128 |
this.creatures.forEach(c => {
|
129 |
+
c.model.traverse((child) => {
|
130 |
+
if (child.isMesh) {
|
131 |
+
child.material.color.set(color);
|
132 |
+
c.model.scale.set(scale, scale, scale);
|
133 |
+
}
|
134 |
+
});
|
135 |
});
|
136 |
toggleEditor(); // Hide editor after applying
|
137 |
}
|
138 |
|
139 |
update() {
|
140 |
this.creatures.forEach(creature => {
|
141 |
+
creature.model.position.x += (Math.random() - 0.5) * creature.speed;
|
142 |
+
creature.model.position.z += (Math.random() - 0.5) * creature.speed;
|
143 |
+
creature.model.position.x = Math.max(-50, Math.min(50, creature.model.position.x));
|
144 |
+
creature.model.position.z = Math.max(-50, Math.min(50, creature.model.position.z));
|
145 |
});
|
146 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
147 |
}
|
148 |
|
149 |
let game;
|
150 |
document.addEventListener("DOMContentLoaded", () => {
|
151 |
+
game = new TribalStage();
|
152 |
game.init();
|
153 |
});
|