game rules - object triggers set up
This commit is contained in:
@@ -28,6 +28,7 @@ export default {
|
|||||||
assignCharacter(e){
|
assignCharacter(e){
|
||||||
this.modelValue.go = e.id;
|
this.modelValue.go = e.id;
|
||||||
this.modelValue.title = e.name
|
this.modelValue.title = e.name
|
||||||
|
this.modelValue.exclude = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { getBoundingBox, getBoundingBoxCenterPoint, getBoundingBoxMaxLength, centerOrigin } from "@/lib/MeshUtils";
|
import { getBoundingBox, getBoundingBoxCenterPoint, getBoundingBoxMaxLength, centerOrigin } from "@/lib/MeshUtils";
|
||||||
import { EventDispatcher } from "three";
|
import { EventDispatcher, SphereGeometry, Mesh, MeshStandardMaterial, BackSide } from "three";
|
||||||
|
|
||||||
class GenericObject extends EventDispatcher{
|
class GenericObject extends EventDispatcher{
|
||||||
constructor(engine, data){
|
constructor(engine, data){
|
||||||
@@ -9,6 +9,20 @@ class GenericObject extends EventDispatcher{
|
|||||||
this.object = centerOrigin(this.source.scene)
|
this.object = centerOrigin(this.source.scene)
|
||||||
|
|
||||||
if (!data.exclude){
|
if (!data.exclude){
|
||||||
|
const bckGeometry = new SphereGeometry(getBoundingBoxMaxLength(this.object.userData.bbox)/2,8,8)
|
||||||
|
const bckMesh = new Mesh(bckGeometry, new MeshStandardMaterial({
|
||||||
|
transparent: true,
|
||||||
|
opacity:1, color: 0xaaaaaa,
|
||||||
|
alphaMap: await engine.loadTexture('locked.webp', '/static/textures/'),
|
||||||
|
}))
|
||||||
|
this.object.add(bckMesh)
|
||||||
|
engine.motionQueue.add(
|
||||||
|
{ o: bckMesh, a:{
|
||||||
|
material: { opacity: k=>0.11 + 0.52*Math.sin(k*Math.PI)},
|
||||||
|
rotation: { y: k=>k*Math.PI*2},
|
||||||
|
scale: (k,s)=>s.setScalar(1+0.11*Math.sin(2*k*Math.PI))
|
||||||
|
}, r: true, t: 3 },
|
||||||
|
)
|
||||||
engine.clickable.add(this.object, async e=>{
|
engine.clickable.add(this.object, async e=>{
|
||||||
this.object._active = !this.object._active;
|
this.object._active = !this.object._active;
|
||||||
if (engine.dashboard){
|
if (engine.dashboard){
|
||||||
|
|||||||
@@ -1,18 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-card v-if="modelValue.go">
|
<div v-if="modelValue.go">
|
||||||
<v-card-item>
|
<v-number-input density="compact" :precision="null" label="Particle width" v-model="modelValue.x"></v-number-input>
|
||||||
<v-number-input density="compact" :precision="null" label="Particle width" v-model="modelValue.x"></v-number-input>
|
<v-number-input density="compact" :precision="null" label="Particle height" v-model="modelValue.y"></v-number-input>
|
||||||
<v-number-input density="compact" :precision="null" label="Particle height" v-model="modelValue.y"></v-number-input>
|
|
||||||
|
|
||||||
<v-number-input density="compact" :precision="null" label="Area width" v-model="modelValue.w"></v-number-input>
|
<v-number-input density="compact" :precision="null" label="Area width" v-model="modelValue.w"></v-number-input>
|
||||||
<v-number-input density="compact" :precision="null" label="Area length" v-model="modelValue.h"></v-number-input>
|
<v-number-input density="compact" :precision="null" label="Area length" v-model="modelValue.h"></v-number-input>
|
||||||
|
|
||||||
<v-number-input density="compact" label="Count" v-model="modelValue.count"></v-number-input>
|
<v-number-input density="compact" label="Count" v-model="modelValue.count"></v-number-input>
|
||||||
|
|
||||||
<v-img :src="`/asset/thumb/${modelValue.go}.webp`" />
|
<v-img :src="`/asset/thumb/${modelValue.go}.webp`" />
|
||||||
<div class="text-caption text-center">{{ modelValue.title }}</div>
|
<div class="text-caption text-center">{{ modelValue.title }}</div>
|
||||||
</v-card-item>
|
</div>
|
||||||
</v-card>
|
|
||||||
<asset-selector @select="assignTexture" :type="['Texture']">
|
<asset-selector @select="assignTexture" :type="['Texture']">
|
||||||
<template v-slot:activator="props">
|
<template v-slot:activator="props">
|
||||||
<v-btn v-bind="props" prepend-icon="mdi-video-box" color="deep-orange-darken-4" block>Choose image object</v-btn>
|
<v-btn v-bind="props" prepend-icon="mdi-video-box" color="deep-orange-darken-4" block>Choose image object</v-btn>
|
||||||
@@ -43,6 +41,7 @@ export default {
|
|||||||
this.modelValue.count = 1000;
|
this.modelValue.count = 1000;
|
||||||
this.modelValue.w = 50;
|
this.modelValue.w = 50;
|
||||||
this.modelValue.h = 50;
|
this.modelValue.h = 50;
|
||||||
|
this.modelValue.exclude = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<teleport to=".scene-designer .lines" v-if="active">
|
||||||
|
<OffsetLine v-for="(t, i) in modelValue.activationTriggers" :x1="vd.x1" :y1="vd.y1"
|
||||||
|
:x2="parent.data.items.find(i=>i.data.id == t)?.vd.x1"
|
||||||
|
:y2="parent.data.items.find(i=>i.data.id == t)?.vd.y1" :o1="52" :o2="52"
|
||||||
|
class="trigger" marker-start="url(#arrow)" ></OffsetLine>
|
||||||
|
</teleport>
|
||||||
<teleport to=".scene-designer .game-objects" v-if="active">
|
<teleport to=".scene-designer .game-objects" v-if="active">
|
||||||
<g @mousedown="$emit('target', {target:vd, attrs:['x1', 'y1'], delta: true})" :class="{gameObject: true, selected}"
|
<g @mousedown="$emit('target', {target:vd, attrs:['x1', 'y1'], delta: true})" :class="{gameObject: true, selected}"
|
||||||
v-show="showInView">
|
v-show="showInView">
|
||||||
@@ -18,14 +24,21 @@
|
|||||||
</asset-selector>
|
</asset-selector>
|
||||||
<v-form class="pt-4">
|
<v-form class="pt-4">
|
||||||
<v-text-field density="compact" :label="l.name" v-model="modelValue.title"></v-text-field>
|
<v-text-field density="compact" :label="l.name" v-model="modelValue.title"></v-text-field>
|
||||||
<v-text-field density="compact" :label="l.id" v-model="modelValue.id"></v-text-field>
|
<!-- <v-text-field density="compact" :label="l.id" v-model="modelValue.id"></v-text-field> -->
|
||||||
<v-number-input density="compact" label="Completion points" v-model="modelValue.points"></v-number-input>
|
<v-number-input density="compact" label="Completion points" v-model="modelValue.points"></v-number-input>
|
||||||
</v-form>
|
</v-form>
|
||||||
|
<v-container v-if="selected && modelValue.type">
|
||||||
|
<component :is="modelValue.type" v-model="mv"></component>
|
||||||
|
</v-container>
|
||||||
|
|
||||||
|
<v-card title="Activation requirements" v-if="modelValue.type != 'CharacterObject'">
|
||||||
|
<v-number-input density="compact" label="Level score should be above" v-model="modelValue.activationScore"></v-number-input>
|
||||||
|
<v-select density="compact" label="Following elements should be completed" v-model="modelValue.activationTriggers"
|
||||||
|
:items="parent.data.items.filter(v=>!v.data.exclude && v.data!==modelValue).map(v=>({title: v.data.title, value: v.data.id}))" multiple ></v-select>
|
||||||
|
</v-card>
|
||||||
</v-card>
|
</v-card>
|
||||||
|
|
||||||
<v-container v-if="selected && modelValue.type">
|
|
||||||
<component :is="modelValue.type" v-model="mv"></component>
|
|
||||||
</v-container>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -39,10 +52,11 @@ import MazeQuizGame from '../InteractiveObjects/MazeQuizGame/MazeQuizGame.vue';
|
|||||||
import Particles from '../InteractiveObjects/Particles.vue';
|
import Particles from '../InteractiveObjects/Particles.vue';
|
||||||
import GenericObject from '../InteractiveObjects/GenericObject.vue';
|
import GenericObject from '../InteractiveObjects/GenericObject.vue';
|
||||||
import CharacterObject from '../InteractiveObjects/CharacterObject.vue';
|
import CharacterObject from '../InteractiveObjects/CharacterObject.vue';
|
||||||
|
import OffsetLine from './OffsetLine.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
emits:['target', 'preview'],
|
emits:['target', 'preview'],
|
||||||
components: { SvgIcon, GenericObject, CharacterObject, VideoPlayer, PuzzleGame1, PuzzleGame2, MazeQuizGame, Particles, },
|
components: { SvgIcon, OffsetLine, GenericObject, CharacterObject, VideoPlayer, PuzzleGame1, PuzzleGame2, MazeQuizGame, Particles, },
|
||||||
data(){
|
data(){
|
||||||
return {
|
return {
|
||||||
active: false
|
active: false
|
||||||
@@ -51,6 +65,7 @@ export default {
|
|||||||
mounted(){
|
mounted(){
|
||||||
this.active = true;
|
this.active = true;
|
||||||
this.modelValue.points ??= 10;
|
this.modelValue.points ??= 10;
|
||||||
|
this.modelValue.activationScore ??= 0;
|
||||||
},
|
},
|
||||||
props:{
|
props:{
|
||||||
//context: Object,
|
//context: Object,
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<template>
|
||||||
|
<line :x1="ox1" :y1="oy1" :x2="ox2" :y2="oy2"></line>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props:{
|
||||||
|
x1: Number, y1: Number, x2: Number, y2: Number,
|
||||||
|
o1: Number, o2: Number
|
||||||
|
},
|
||||||
|
data(){
|
||||||
|
return {
|
||||||
|
ox1:0, ox2:0, oy1:0, oy2:0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted(){
|
||||||
|
this.calc();
|
||||||
|
this.$watch(
|
||||||
|
(vm) => (vm.x1, vm.y1, vm.x2, vm.y2, vm.o1, vm.o2, Date.now()),
|
||||||
|
this.calc
|
||||||
|
)
|
||||||
|
},
|
||||||
|
methods:{
|
||||||
|
calc: function(){
|
||||||
|
let dx = this.x2 - this.x1, dy = this.y2 - this.y1;
|
||||||
|
let a = Math.atan2(dy, dx);
|
||||||
|
let h = Math.sqrt(dx*dx + dy*dy);
|
||||||
|
this.ox1 = this.x1 + this.o1 * Math.cos(a);
|
||||||
|
this.oy1 = this.y1 + this.o1 * Math.sin(a);
|
||||||
|
this.ox2 = this.x1 + (h-this.o1) * Math.cos(a);
|
||||||
|
this.oy2 = this.y1 + (h-this.o1) * Math.sin(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -19,7 +19,14 @@
|
|||||||
<svg class="scene-designer" @resize="resize" :width="viewBox.w" :height="viewBox.h"
|
<svg class="scene-designer" @resize="resize" :width="viewBox.w" :height="viewBox.h"
|
||||||
:viewBox="`${vb.x} ${vb.y} ${vb.w} ${vb.h}`" x="0" y="0" xmlns="http://www.w3.org/2000/svg"
|
:viewBox="`${vb.x} ${vb.y} ${vb.w} ${vb.h}`" x="0" y="0" xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<defs>
|
||||||
|
<marker id="arrow" viewBox="0 0 10 10" refX="5" refY="5"
|
||||||
|
markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||||
|
<path d="M 0 0 L 10 5 L 0 10 z" />
|
||||||
|
</marker>
|
||||||
|
</defs>
|
||||||
<SvgRectangle v-model="selector" class="selector"></SvgRectangle>
|
<SvgRectangle v-model="selector" class="selector"></SvgRectangle>
|
||||||
|
<g class="lines"></g>
|
||||||
<g class="tasks"></g>
|
<g class="tasks"></g>
|
||||||
<g class="game-objects"></g>
|
<g class="game-objects"></g>
|
||||||
<g class="scenes"></g>
|
<g class="scenes"></g>
|
||||||
|
|||||||
@@ -57,8 +57,8 @@ function autoScale(object, mk = 1) {
|
|||||||
|
|
||||||
function centerOrigin(object){
|
function centerOrigin(object){
|
||||||
let result = new Group();
|
let result = new Group();
|
||||||
let bb = getBoundingBox(object);
|
result.userData.bbox = getBoundingBox(object);
|
||||||
let position = getBoundingBoxCenterPoint(bb, object.position).negate();
|
let position = getBoundingBoxCenterPoint(result.userData.bbox, object.position).negate();
|
||||||
object.position.copy(position)
|
object.position.copy(position)
|
||||||
result.add(object);
|
result.add(object);
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -18,7 +18,10 @@ class MotionEngine {
|
|||||||
if (mode == 'offset') {
|
if (mode == 'offset') {
|
||||||
target[key] = (initial[key] || 0) + value * k;
|
target[key] = (initial[key] || 0) + value * k;
|
||||||
} else if (typeof (value) == 'function') {
|
} else if (typeof (value) == 'function') {
|
||||||
target[key] = value(k);
|
let v = value(k, target[key]);
|
||||||
|
if (target[key] !== v){
|
||||||
|
target[key] = v;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
target[key] = (initial[key] || 0) + (value - (initial[key] || 0)) * k;
|
target[key] = (initial[key] || 0) + (value - (initial[key] || 0)) * k;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,6 +77,10 @@ video{
|
|||||||
stroke: rgb(213, 226, 231);
|
stroke: rgb(213, 226, 231);
|
||||||
stroke-width: calc( 2px * var(--svg-scale) );
|
stroke-width: calc( 2px * var(--svg-scale) );
|
||||||
}
|
}
|
||||||
|
line.trigger, marker#arrow path {
|
||||||
|
stroke: rgb(244, 215, 230);
|
||||||
|
fill: rgb(172, 105, 139);
|
||||||
|
}
|
||||||
g.selector {
|
g.selector {
|
||||||
line {
|
line {
|
||||||
stroke-dasharray: 0 calc(8 * var(--svg-scale)) 0;
|
stroke-dasharray: 0 calc(8 * var(--svg-scale)) 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user