} Скрыть} Скрыть
На сайте:
130 человека: Воронов и 129 гостей
Обсуждаем:

Владас

Блог-свалка :)

Давно я обратил внимание на кнопочку "Блог"... Ну блог так блог, не зря же тут эта кнопочка :)
Буду тут выкладывать свои задумки, наработки, куски кода, заброшенные проекты, WIP'ы и прочий мусор :) (надеюсь никто не против)
Может быть что то из всего этого даже кому то поможет...


И для начала выложу несколько скриптов (не все написано оптимально, я ж не крутой кодер, главное что кое как да работают :) ), точнее это один скрипт состоящий из кучи функций, которые можно вызывать актуатором Python (такой подход порой эффективнее и компактнее чем куча отдельных маленьких скриптов).
from bge import logic as G, events as E
from mathutils import *
from random import *
  
G.loadGlobalDict()
  
#меняет разрешение (качество) текста и сам текст (полезно чтобы не делать
#несколько разных текстовых объектов, а сделать клоны с другими значениями TEXT),
#требуется проперти Res с целым числом, и TEXT с текстом на который поменять.
def Res(cont):
    own = cont.owner
    own.resolution = own.get("Res", 3)
    
    own["Text"] = own.get("TEXT", own["Text"])
  
#нужная функция, используется для функций FadeColor и FadeScale, без нее они не работают.
def Change(id, start, end, cycles = 600, rem = G.getCurrentScene()):
    id = str(id)
  
    if not id in rem:
        rem[id] = {
        "Cycle" : 0,
        "ResultBackup" : start,
        "AddBackup" : (end - start) / cycles}
        
        return start
                                
    if id in rem and rem[id]["Cycle"] < cycles:
        rem[id]["Cycle"] += 1
        
        rem[id]["ResultBackup"] += rem[id]["AddBackup"]
                                
        if rem[id]["Cycle"] >= cycles:
            del rem[id]
            
            return end
                                                                
        return rem[id]["ResultBackup"]
  
#плавное изменение цвета объекта по сообщению (уже не помню почему так сделал),
#требует сенсор "сообщение" в импульсном режиме (оба уровня), тело получаемого
#сообщения должно состоять из: красный/зеленый/синий/количество_логических_тиков.
#Тоесть "1/1/1/60" для изменения цаета на белый за 60 тиков
def FadeColor(cont):
    sce = G.getCurrentScene()
    own = cont.owner
    
    if "FadeColor" in cont.sensors:
        fs = cont.sensors["FadeColor"]
        
        if fs.positive:
            own["FColor"] = fs.bodies[0].split("/")[0]
            own["TColor"] = fs.bodies[0].split("/")[1]
            
            if len(fs.bodies[0].split("/")) > 2: own["CCycles"] = int(fs.bodies[0].split("/")[2])
                                                                
    if own.get("FColor"):
        FC = Vector([float(n) for n in own.get("FColor", "1,1,1,1").split(",")])
        TC = Vector([float(n) for n in own.get("TColor", "0,0,0,0").split(",")])
        
        own.color = Change(id(own), FC, TC, own.get("CCycles", 600), own)
        
        if own.color == TC:
            del own["FColor"]
            del own["TColor"]
            del own["CCycles"]
                                                                                                
            for act in cont.actuators:
                cont.activate(act)
  
#аналогично предыдущему, только изменяет размер объекта.
def FadeScale(cont):
    sce = G.getCurrentScene()
    own = cont.owner
    
    if "FadeScale" in cont.sensors:
        fs = cont.sensors["FadeScale"]
        
        if fs.positive:
            own["FScale"] = fs.bodies[0].split("/")[0]
            own["TScale"] = fs.bodies[0].split("/")[1]
            
            if len(fs.bodies[0].split("/")) > 2: own["SCycles"] = int(fs.bodies[0].split("/")[2])
    
    if own.get("FScale"):
        FS = Vector([float(n) for n in own.get("FScale", "1,1,1").split(",")])
        TS = Vector([float(n) for n in own.get("TScale", "0,0,0").split(",")])
        
        own.localScale = Change(id(own), FS, TS, own.get("SCycles", 600), own)
        
        if own.localScale == TS:
            del own["FScale"]
            del own["TScale"]
            del own["SCycles"]
  
            for act in cont.actuators:
                cont.activate(act)
  
#для создания курсора в меню игры, требует сенсор Mouse (курсор над любым)
#в импульсном режиме истины и поверхность на весь экран столкновения с которой
#и будут копироваться для объекта (копируются положение по X и Y).
def Cursor(cont):
    own = cont.owner
    mouse = cont.sensors["Mouse"]
    
    own.worldPosition.x = mouse.hitPosition.x
    own.worldPosition.y = mouse.hitPosition.y
    
    for act in cont.actuators:
        cont.activate(act)
  
#сохраняет все свойства объекта в globalDict, если есть свойство SaveName
#сохранит под указанным там названием, иначе сохранит под именем объекта.
def SaveProps(cont):
    own = cont.owner
    
    G.globalDict[own.get("SaveName", own.name)] = {x:own[x] for x in own.getPropertyNames() if x != "SaveName"}
    
    G.saveGlobalDict()
    
    for act in cont.actuators:
        cont.activate(act)
  
#загружает сохраненные свойства.
def LoadProps(cont):
    own = cont.owner
    prop = G.globalDict.get(own.get("SaveName", own.name))
    
    if prop:
        for x in prop:
            own[x] = prop[x]
            
    for act in cont.actuators:
        cont.activate(act)
  
#удаляет все сохранения если нет свойства DelSaves, иначе удаляет только те,
#что указаны в DelSaves через запятую (без пробела).
def DelSaves(cont):
    own = cont.owner
    
    if "DelSaves" in own: own["DelSaves"] = [G.globalDict[sav] for sav in own["DelSaves"].split(",")]
    else: own["DelSaves"] = [sav for sav in G.globalDict]
    
    for save in own["DelSaves"]: del save
    
    G.saveGlobalDict()
    
    for act in cont.actuators:
        cont.activate(act)
  
#поворачивает объект в сторону его движения.
def Ballist(cont):
    cont.owner.alignAxisToVect(-cont.owner.getLinearVelocity())
  
#требует сенсор Collision, вычитает урон (свойство Damage) из жизней столкнувшегося
#с ним объета (свойство Health). Если есть свойство Force, тогда еще и толкает объект.
#Если есть свойство HitAll, то выбивает жизни у всех столкнувшихся, иначе только у первого.
def HitOnColl(cont):
    own = cont.owner
    sce = G.getCurrentScene()
    objs = cont.sensors["Collision"].hitObjectList
    
    if objs:
        if "HitAll" in own: klvo = len(objs)
        else: klvo = 1
        
        for i in range(0, klvo):
            if "Damage" in own and "Health" in objs[i]:
                objs[i]["Health"] -= own["Damage"]
                              
            if "Force" in own and objs[i].getPhysicsId() != 0:
                norm = (objs[i].worldPosition - own.worldPosition).normalized() * own["Force"]
                
                objs[i].applyImpulse(objs[i].worldPosition, norm)
            
        for act in cont.actuators:
            cont.activate(act)
  
#аналогично, требует свойства Rad с радиусом поражения, Damage с уроном и Force с силой отбрасывания.
def Explosion(cont):
    own = cont.owner
    sce = G.getCurrentScene()
    
    if cont.sensors["Collision"].positive:
        objs = [obj for obj in sce.objects if obj.getDistanceTo(own) <= own["Rad"] and obj != own]
        
        if len(objs) > 0:
            for obj in objs:
                if "Health" in obj:
                    dam = (own["Damage"] / own["Rad"]) * (own["Rad"] - obj.getDistanceTo(own))
                    
                    obj["Health"] -= dam
                    
                if obj.getPhysicsId() != 0:
                    norm = (obj.worldPosition - own.worldPosition).normalized()
                    norm *= (own["Force"] / own["Rad"]) * (own["Rad"] - obj.getDistanceTo(own))
                    
                    obj.applyImpulse(obj.worldPosition, norm)
            
        for act in cont.actuators:
            cont.activate(act)
  
#прокрутка UV, хорошо для водопадов например :)
#Требует сенсор Always в импульсном режиме и свойства SpeedX и SpeedY
#со скоростью прокрутки, index и array (уже не помню зачем эти два).
def UVscroll(cont):
    own = cont.owner
    mesh = own.meshes[0]
    
    array = mesh.getVertexArrayLength(own.get('array', 0))
    
    for v in range(0,array):
        vertex = mesh.getVertex(own.get('index', 0) ,v)
        
        UV = vertex.getUV()
        UV[0] += own.get('SpeedX', 0.001)
        UV[1] += own.get('SpeedY', 0.001)
        
        vertex.setUV(UV)
1501769470
Последнее время я потихоньку изучал фильтры (методом проб и ошибок и ковырянием чужих фильтров), зянятная это штука :)
И вот наконец что-то получилось, и я подумал почему бы не выложить это тут?
(Немного коряво, конечно, но, думаю задумку свою я осуществил :) )

Фильтр на красный цвет
Фильтр пропускает только красный цвет, оставляя остальное черно-белым. С помощю параметра strenght в фильтре, можно регулировать силу фильтра, ну как бы чувствительность к красному (высокие значения позволяют фильтру пропускать только "самый красный" :) ). Звук работающего проектора и дрожжание частично логикой (если это не нужно - можно просто убрать, оставив только фильтр).


Blend:
Filter_R.blend
Управление:
•WS - вперед/назад;
•AD - впаво/влево;
•Space/Ctrl - вверх/вниз;
•F - включить/выключить фильтр;
1501201774
Скрипт сохранения/загрузки
Сохраняет отмеченные свойством объекты в файл (по умолчанию Save.sav) в папку Saves.
Скрипт, наверное, немного корявый, сохранения в итоге весят многовато, но зато нету проблем с кириллицей (во всяком случае у меня из папки с русским названием скрипт работал, в отличии от варианта с globalDict) :) тут еще есть над чем поработать, если кому-то это оказалось полезным - буду дорабатывать, шлифовать и полировать :)

Свойства:
Для объекта, на котором весит скрипт, требуется свойство SaveName с именем сохранения;
Для сохраняемых объектов требуется свойство SaveObj, в нем через запятую перечислить что нужно сохранять:

•T - положение/вращение/размер (.worldTransform);
•Ph - сохранение физики (ну там линейная скорость, скорость вращения...);
•Ms - сохранение веса;
•P - свойства;
•C - цвет;
•M - меш (сохраняется только имя. При загрузке скрипт попытается сменить меш с помощю .replaceMesh(сохраненное_имя) );
•V - видимость;
•S - состояние (.state).

Сенсоры:
Любые (все подключенные сенсоры должны быть активированы).

Актуаторы:
Нету.

Как пользоваться:
Вызывать одну из фкнкций (Save/Load/Del) с помощю контроллера 'Python' в режиме модуля.

Скрипт:
Скрипт был длинноватым, и я решил что бленд-файла будет достаточно :)

.blend:
save.blend
Управление:
•Пробел - добавить кубик;
•1 - сохранить;
•2 - загрузить;
•3 - удалить сохранение.
1496612599
Скрипт движения платформы

Свойства:
•Range (строка, скрипт конвертирует в вектор) - Диапазон движения. 3 числа через запятую с пробелом.
•Time (целое число) - Время прохождения диапазона (в логических тиках).
•Pause (целое число) - Время ожидания перед возвратом (в логических тиках).

Сенсоры:
•Always (импульсный режим)
•Collision (назвать Coll) - если подключить этот сенсор, включается костыль для удержания объектов на платформе. (На Character не действует!)

Актуаторы:
Любые. Для активации во время движения, перед именем актуатора дописать "Move", для разовой активации при остановке - "Stop" (Например "Move_Sound" или "StopSound").

Скрипт:
from bge import logic as G
from mathutils import Vector as vec
    
cont = G.getCurrentController()
own = cont.owner
spd = own.get('Time', 60)
paus = own.get('Pause', 30)
  
active = [sens.positive for sens in cont.sensors if sens.name != 'Coll']
  
if not False in active:
    
    if own.get('cyc', -paus) <= -paus:
        own['cyc'] = spd
        own['clist'] = []
        
        if not 'shag' in own:
            rang = vec([float(i) for i in own.get('Range', "1, 1, 1").split(', ')])
            own['shag'] = rang / spd
        
        else: own['shag'] *= -1
      
    if own['cyc'] > 0:
        own.worldPosition += own['shag']
        
        for act in cont.actuators:
            if act.name[0:4] == 'Move':
                cont.activate(act)
                
            elif act.name[0:4] == 'Stop':
                cont.deactivate(act)
        
    elif own['cyc'] == 0:
        for act in cont.actuators:
            if act.name[0:4] == 'Move':
                cont.deactivate(act)
       
            elif act.name[0:4] == 'Stop':
                cont.activate(act)
    
    if 'Coll' in cont.sensors and own['cyc'] >= 0:
        coll = cont.sensors['Coll']
        znk = (own['cyc'] > 0) * 2 - 1
        
        for obj in coll.hitObjectList:
            
            if (znk > 0 and obj not in own['clist']) or (znk < 0 and obj in own['clist']):
                vel = obj.getLinearVelocity(False) + (own['shag'] * 60 * znk)
                obj.setLinearVelocity(vel, False)
                
                own['clist'].append(obj)
      
    own['cyc'] -= 1
Blend:
platform.blend
Николай: Платформа ездит, а игрок стоит... вот то беда  ! А потом упадет - и еще больше беда  И если бы в свойстве Range прописывалось направление только в одну сторону, а не от центра + -, еще бы лучше было бы. А если прописать звук цикличный, и паузу при остановке - ну просто Портал, и ...
Владас: Про игрока - это беда физики, сам вчера в очередной раз разочаровался (скрипт то для игры с платформами делал), сейчас думаю как это править (тут без костылей для игрока не обойтись ).И если бы в свойстве Range прописывалось направление только в одну сторону, а не от центра + -Незнаю ...   k 1
... k +1
Николай: Да как бы - платформа как в Портал, и звук к ней - это больное место в BGE. Если справишся, будешь опять великим решателем проблем. Я в свою очередь, с Божьей помощью, сделаю комнату с платформами, кубом, дверьми...  - в стиле Portal 1. Пример будет доступен во ВСЕМ МИРЕ ! Даже поставим ...   k 1
Николай: Там кароче актуатор наверное как в скрипте надо было обозвать... я таки понял, к счастью.  А ты не мог бы еще прописать включения и выключения через свойство "Active"? 223_platform_test.blend - таки саунд ОN, если и мозги On... А может привязку Игрока через родителя  - Parent? Как бы ...   k 1
Весь блендер на карте инфографики. Изучение блендер на одном постере. Горячие клавиши. Скачай и распечатай постер --> Горячие клавиши Блендер