Skip to content

Commit f9dc05f

Browse files
committed
ingredients
1 parent 3c10b5b commit f9dc05f

2 files changed

Lines changed: 132 additions & 30 deletions

File tree

combined-ingredients.md

Lines changed: 132 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -946,7 +946,8 @@ export default class PlayerController extends Behavior {
946946
});
947947
}
948948

949-
onTickClient(): void {
949+
onTick(): void {
950+
if (!this.game.isClient()) return;
950951
if (!this.hasAuthority()) return;
951952

952953
const deltaTime = this.game.physics.tickDelta / 1_000; // Convert to seconds
@@ -1370,6 +1371,121 @@ export default class Movement extends Behavior {
13701371

13711372
```
13721373

1374+
Here's an example of an enemy that chases a player:
1375+
```ts
1376+
import {
1377+
Behavior,
1378+
ColoredSquare,
1379+
EntityCollision,
1380+
syncedValue,
1381+
Vector2,
1382+
} from "@dreamlab/engine";
1383+
import PlayerController from "./player-controller.ts";
1384+
1385+
export default class Enemy extends Behavior {
1386+
@syncedValue()
1387+
speed = 3;
1388+
1389+
@syncedValue()
1390+
chaseRange = 15;
1391+
1392+
@syncedValue()
1393+
knockbackForce = 15;
1394+
1395+
@syncedValue()
1396+
color = "#ff4444";
1397+
1398+
private player: any = null;
1399+
private direction = new Vector2(1, 0); // Start moving right
1400+
private lastPlayerPosition = Vector2.ZERO;
1401+
1402+
onInitialize(): void {
1403+
if (!this.game.isClient()) return;
1404+
1405+
// Set enemy color
1406+
const coloredSquare = this.entity._.ColoredSquare?.cast(ColoredSquare);
1407+
if (coloredSquare) {
1408+
coloredSquare.color = this.color;
1409+
}
1410+
1411+
// Listen for collisions
1412+
this.listen(this.entity, EntityCollision, (e: EntityCollision) => {
1413+
if (e.started) this.onCollide(e.other);
1414+
});
1415+
}
1416+
1417+
onTickClient(): void {
1418+
if (!this.game.isClient()) return;
1419+
1420+
// Find the player
1421+
this.findPlayer();
1422+
1423+
if (this.player) {
1424+
const playerPos = this.player.pos;
1425+
const enemyPos = this.entity.pos;
1426+
const distance = playerPos.distance(enemyPos);
1427+
1428+
// Chase player if within range
1429+
if (distance <= this.chaseRange && distance > 0.5) {
1430+
this.direction = playerPos.sub(enemyPos).normalize();
1431+
this.lastPlayerPosition = playerPos;
1432+
} else if (distance > this.chaseRange) {
1433+
// Continue in last known direction if player is out of range
1434+
if (this.lastPlayerPosition.magnitude() > 0) {
1435+
this.direction = this.lastPlayerPosition.sub(enemyPos).normalize();
1436+
}
1437+
}
1438+
}
1439+
1440+
// Move the enemy
1441+
const movement = this.direction.mul(this.speed * (this.game.physics.tickDelta / 1000));
1442+
this.entity.pos = this.entity.pos.add(movement);
1443+
}
1444+
1445+
private findPlayer(): void {
1446+
if (!this.player) {
1447+
// Look for player in the world
1448+
const worldChildren = Array.from(this.game.world.children.values());
1449+
this.player = worldChildren.find(entity =>
1450+
entity.name.startsWith("Player") && entity.hasBehavior(PlayerController)
1451+
);
1452+
1453+
// If not found in world, look in local (for singleplayer)
1454+
if (!this.player) {
1455+
const localChildren = Array.from(this.game.local!.children.values());
1456+
this.player = localChildren.find(entity =>
1457+
entity.name.startsWith("Player") && entity.hasBehavior(PlayerController)
1458+
);
1459+
}
1460+
}
1461+
}
1462+
1463+
private onCollide(other: any): void {
1464+
if (!other.hasBehavior(PlayerController)) return;
1465+
1466+
const playerController = other.getBehavior(PlayerController);
1467+
const playerPos = other.pos;
1468+
const enemyPos = this.entity.pos;
1469+
1470+
// Check if player is above the enemy (jumping on head)
1471+
const verticalDiff = playerPos.y - enemyPos.y;
1472+
const horizontalDiff = Math.abs(playerPos.x - enemyPos.x);
1473+
console.log(verticalDiff, horizontalDiff);
1474+
1475+
// If player is significantly above and close horizontally, they jumped on the enemy
1476+
if (verticalDiff > 0.5 && horizontalDiff < 1.0) {
1477+
// Player jumped on enemy - destroy enemy and give player a small bounce
1478+
playerController.onEnemyDefeated();
1479+
this.entity.destroy();
1480+
} else {
1481+
// Enemy hits player - knock them back
1482+
const knockbackDirection = playerPos.sub(enemyPos).normalize();
1483+
playerController.onEnemyHit(knockbackDirection, this.knockbackForce);
1484+
}
1485+
}
1486+
}
1487+
```
1488+
13731489
---
13741490

13751491

@@ -1425,6 +1541,13 @@ Transform.position is relative to parent. .pos is absolute position in the world
14251541
When answering, be sure to think about:
14261542
1. Carefully consider whether you want your code running on the server or client.
14271543
2. If you want server authority, run in onTickServer. If it's client-only, run in onTickClient. If it has anything to do with player control, you probably want to tick on the client.
1544+
3. If you notice that most of the entities in the world are under "local" or you see the presence of a .singleplayer file, it means you are editing a singleplayer game. In this case, you should write client side code and create new entities under "local".
1545+
1546+
for client side code, do the following at the top of any onTick, onInitialize
1547+
if (!this.game.isClient()) return;
1548+
1549+
for server side code, do the following:
1550+
if (!this.game.isServer()) return;
14281551

14291552
Additionally, think about what methods you are going to use/import. Only use methods that exist from other files or the Dreamlab API. Plan for everything you're going to need to do and what you have to import. If you need any sort of game engine feature, list it in your response and where it's going to be imported from. Do not invent new APIs.
14301553

@@ -1452,9 +1575,14 @@ addBehavior(newEntity, "src/something.ts", {someValue: 25});
14521575
</editCode>
14531576
</editor>
14541577

1578+
If the player asks specifically for you to create a prefab, do not place it in the world or local roots, ONLY create an entity in "prefabs".
1579+
14551580
You should think carefully before deciding whether to write a Behavior script or an editor script. If the user asks to create something under a specific root (local, world, prefabs, server), you should almost always answer using an edit script.
14561581
Note that all transforms/positions are local and are scaled and positioned relative to the parent. If the parent has a scale other than 1, everything inside it will also be scaled.
14571582

1583+
If you need to access the camera, use Camera.getActive(this.game) instead of a hard reference or a synced value.
1584+
1585+
14581586
Notes:
14591587
1. Entities cannot change type. If you want to add a Collider to an existing entity, create it as a child.
14601588
2. Entities do not have components. They are a single entity of a single type. Here is a list of all entities:
@@ -1480,4 +1608,6 @@ Notes:
14801608

14811609
If you're simply modifying an existing script, this will not be needed.
14821610

1483-
Feel free to ask the user questions before answering if you feel you do not have enough detail.
1611+
Feel free to ask the user questions before answering if you feel you do not have enough detail.
1612+
1613+
If you have enough detail, do not ask for confirmation. Just go.

src/theme/SearchBar.tsx

Lines changed: 0 additions & 28 deletions
This file was deleted.

0 commit comments

Comments
 (0)