object touch events implemented

This commit is contained in:
azykov@mail.ru
2026-06-13 13:18:03 +03:00
parent 209ff3f710
commit 1ed3203ec5
6 changed files with 40 additions and 13 deletions
@@ -1,13 +1,13 @@
import * as Blockly from "blockly";
import { javascriptGenerator } from "blockly/javascript";
import { javascriptGenerator, Order } from "blockly/javascript";
Blockly.Blocks['object_touch_start_event'] = {
init(this: Blockly.Block) {
this.appendDummyInput('NAME')
this.appendDummyInput()
.appendField('When');
this.appendValueInput('NAME')
this.appendValueInput('OTHER_OBJECT')
.setCheck('Object');
this.appendDummyInput('NAME')
this.appendDummyInput()
.appendField('touches me');
this.setStyle('event_hat');
this.setNextStatement(true);
@@ -15,8 +15,13 @@ Blockly.Blocks['object_touch_start_event'] = {
}
};
javascriptGenerator.forBlock['object_touch_start_event'] = function (_block, _generator) {
return '';
javascriptGenerator.forBlock['object_touch_start_event'] = function (block, generator) {
const otherObjectValue = generator.valueToCode(block, 'OTHER_OBJECT', Order.NONE) || 'undefined';
return `
const touchTarget = ${otherObjectValue};
if (!context.other || !touchTarget || context.other.id !== touchTarget.id)
return;
`;
};
export { };
+6 -3
View File
@@ -6,13 +6,18 @@ export function generateCode(workspace: Blockly.WorkspaceSvg): string {
let result = '';
for (const block of workspace.getTopBlocks(true)) {
if (block.type.endsWith('_event')) {
let body = '';
const eventName = block.type.replace(/_event$/, '');
let body = javascriptGenerator.blockToCode(block, true) as string;
let next = block.getNextBlock();
while (next) {
// opt_thisOnly=true prevents scrub_ from also chaining — we do it manually
body += javascriptGenerator.blockToCode(next, true);
next = next.getNextBlock();
}
body = javascriptGenerator.prefixLines(body, javascriptGenerator.INDENT.repeat(2));
// const args = Array.from(block.getFields())
@@ -22,8 +27,6 @@ export function generateCode(workspace: Blockly.WorkspaceSvg): string {
//TODO use args
const eventName = block.type.replace(/_event$/, '');
result += `eventBus.on(
'${eventName}',
function* handle_${eventName}(context) {
@@ -1,4 +1,4 @@
import type { ObjectType, RuntimeGameObjectInstance, RuntimeObjectInstance } from "../types";
import type { ObjectType, ObjectInstanceRigidBody, RuntimeGameObjectInstance, RuntimeObjectInstance } from "../types";
import { useEffect, useImperativeHandle, useRef, type Ref } from "react";
import { Euler, Quaternion, type Group } from "three";
import { Instance, Instances } from "@react-three/drei";
@@ -7,6 +7,7 @@ import { ConvexHullCollider, RapierRigidBody } from "@react-three/rapier";
import { SyncRigidBody } from "./SyncRigidBody";
import { reaction, runInAction } from "mobx";
import { v3toRapier } from "../utils";
import { state } from "../state";
export type ObjectViewInternalHandle = {
group: Group | null;
@@ -84,6 +85,19 @@ export const ObjectViewInternal = function ({ object, objectType, ref, ...props
gravityScale={object.gravityScale}
position={object.position}
rotation={object.rotation}
onCollisionEnter={props.isEditor ? undefined : (payload) => {
const game = state.game;
if (!game)
return;
const otherHandle = payload.other.rigidBody?.handle;
if (otherHandle === undefined)
return;
const otherObj = Object.values(game.scene.objects)
.find((o) => o.rb()?.handle === otherHandle);
game.emitEvent('object_touch_start', { object: gameObj, other: otherObj });
if (otherObj?.id === game.scene.playerObjectId)
game.emitEvent('player_touch_start', { object: gameObj, other: otherObj });
}}
onSync={(data) => {
runInAction(() => {
object.position = data.position;
+3
View File
@@ -1,3 +1,4 @@
import { toJS } from "mobx";
import type { ScriptContext, ScriptCoroutineContext, ScriptGameEventHandler } from "../types";
import type { ScriptCoroutines } from "./coroutines";
@@ -36,6 +37,8 @@ export class ScriptGameEventBus {
}
emit(event: string, context: Omit<ScriptContext, keyof ScriptCoroutineContext>): void {
console.log('emitting ' + event, toJS(context));
const coroutines = this.handlers[event]
?.map((h) => ({
owner: h.coroutine.thisObject.id,
+3 -2
View File
@@ -2,7 +2,8 @@ import type { V3 } from "../3d";
import type { VoxelGroup } from "../runtime";
import type { ObjectInstance } from "./object";
export type RigidBodyHandle = {
export type ObjectInstanceRigidBody = {
handle: number; // rapier RigidBodyHandle
applyImpulse(impulse: { x: number; y: number; z: number }, wakeUp: boolean): void;
setLinvel(vel: { x: number; y: number; z: number }, wakeUp: boolean): void;
setTranslation(translation: { x: number; y: number; z: number }, wakeUp: boolean): void;
@@ -18,7 +19,7 @@ export type ObjectInstanceRuntimeData = {
boundingBox: { min: V3; max: V3 };
updatedAt: number;
};
rb: () => RigidBodyHandle | null;
rb: () => ObjectInstanceRigidBody | null;
}
export type Runtime<T extends ObjectInstance> = T & ObjectInstanceRuntimeData;
+1
View File
@@ -17,6 +17,7 @@ export type ScriptContext = ScriptCoroutineContext & {
world: World;
scene: Scene;
object?: RuntimeGameObjectInstance;
other?: RuntimeGameObjectInstance;
}
export type ScriptGameEventHandler = (context: ScriptContext) => ScriptCoroutine;