Now FPS character controller demo with fixed shading
This commit is contained in:
@@ -1,5 +1,40 @@
|
||||
{
|
||||
"Entities": [
|
||||
{
|
||||
"CharacterControllerComponent": {
|
||||
"Height": 1.2000000476837158,
|
||||
"Mass": 2500.0,
|
||||
"Radius": 0.20000000298023224
|
||||
},
|
||||
"NameComponent": {
|
||||
"Name": "Player"
|
||||
},
|
||||
"ParentComponent": {
|
||||
"HasParent": false
|
||||
},
|
||||
"TransformComponent": {
|
||||
"Rotation": {
|
||||
"x": 0.0,
|
||||
"y": -0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"Scale": {
|
||||
"x": 1.0,
|
||||
"y": 1.0,
|
||||
"z": 1.0
|
||||
},
|
||||
"Translation": {
|
||||
"x": -15.681736946105957,
|
||||
"y": 17.139999389648438,
|
||||
"z": 10.975672721862793
|
||||
},
|
||||
"Type": "TransformComponent"
|
||||
},
|
||||
"WrenScriptComponent": {
|
||||
"Class": "PlayerScript",
|
||||
"Script": "Scripts/Player.wren"
|
||||
}
|
||||
},
|
||||
{
|
||||
"NameComponent": {
|
||||
"Name": "Trenchbroom map"
|
||||
@@ -8,7 +43,7 @@
|
||||
"HasParent": false
|
||||
},
|
||||
"QuakeMapComponent": {
|
||||
"HasCollisions": false,
|
||||
"HasCollisions": true,
|
||||
"Path": "C:\\Dev\\Nuake\\Editor\\resources\\Maps\\texture_test.map"
|
||||
},
|
||||
"TransformComponent": {
|
||||
@@ -43,7 +78,7 @@
|
||||
"y": 0.9591699838638306,
|
||||
"z": 0.20000000298023224
|
||||
},
|
||||
"IsVolumetric": false,
|
||||
"IsVolumetric": true,
|
||||
"Strength": 10.0,
|
||||
"SyncDirectionWithSky": true,
|
||||
"Type": 0
|
||||
@@ -66,11 +101,54 @@
|
||||
"z": 1.0
|
||||
},
|
||||
"Translation": {
|
||||
"x": 7.035792350769043,
|
||||
"y": 5.795107364654541,
|
||||
"z": -0.9431453943252563
|
||||
"x": -359.2229919433594,
|
||||
"y": -1.979316234588623,
|
||||
"z": -322.51702880859375
|
||||
},
|
||||
"Type": "TransformComponent"
|
||||
},
|
||||
"WrenScriptComponent": {
|
||||
"Class": "TestScript",
|
||||
"Script": "Scripts/entityScript.wren"
|
||||
}
|
||||
},
|
||||
{
|
||||
"CameraComponent": {
|
||||
"CameraInstance": {
|
||||
"AspectRatio": 1.7106741666793823,
|
||||
"Exposure": 1.0,
|
||||
"Fov": 88.0,
|
||||
"Speed": 1.0,
|
||||
"m_Type": 1
|
||||
}
|
||||
},
|
||||
"NameComponent": {
|
||||
"Name": "Camera"
|
||||
},
|
||||
"ParentComponent": {
|
||||
"HasParent": false
|
||||
},
|
||||
"TransformComponent": {
|
||||
"Rotation": {
|
||||
"x": 0.0,
|
||||
"y": -0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"Scale": {
|
||||
"x": 1.0,
|
||||
"y": 1.0,
|
||||
"z": 1.0
|
||||
},
|
||||
"Translation": {
|
||||
"x": 0.0,
|
||||
"y": 0.75,
|
||||
"z": 0.0
|
||||
},
|
||||
"Type": "TransformComponent"
|
||||
},
|
||||
"WrenScriptComponent": {
|
||||
"Class": "CamScript",
|
||||
"Script": "Scripts/Cam.wren"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -78,7 +156,7 @@
|
||||
"m_Environement": {
|
||||
"AmbientColor": {
|
||||
"w": 0.0,
|
||||
"x": null,
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
|
||||
60
Editor/resources/Scripts/Cam.wren
Normal file
60
Editor/resources/Scripts/Cam.wren
Normal file
@@ -0,0 +1,60 @@
|
||||
import "Scripts/ScriptableEntity" for ScriptableEntity
|
||||
import "Scripts/Engine" for Engine
|
||||
import "Scripts/Scene" for Scene
|
||||
import "Scripts/Math" for Vector3, Math
|
||||
import "Scripts/Input" for Input
|
||||
|
||||
class CamScript is ScriptableEntity {
|
||||
|
||||
construct new() {
|
||||
_Pitch = 0
|
||||
_Yaw = 0
|
||||
|
||||
_mouseLastX = 0
|
||||
_mouseLastY = 0
|
||||
Input.HideMouse()
|
||||
}
|
||||
|
||||
init() {
|
||||
|
||||
}
|
||||
|
||||
update(ts) {
|
||||
var x = Input.GetMouseX()
|
||||
var y = Input.GetMouseY()
|
||||
|
||||
var diffx = x - _mouseLastX
|
||||
var diffy = _mouseLastY - y
|
||||
_mouseLastX = x
|
||||
_mouseLastY = y
|
||||
|
||||
var sens = 0.1
|
||||
|
||||
diffx = diffx * sens
|
||||
diffy = diffy * sens
|
||||
|
||||
_Yaw = _Yaw + diffx
|
||||
_Pitch = _Pitch + diffy
|
||||
if(_Pitch > 89) _Pitch = 89
|
||||
if(_Pitch < -89) _Pitch = -89
|
||||
|
||||
var cam = this.GetComponent("Camera")
|
||||
|
||||
var rad_yaw = Math.Radians(_Yaw)
|
||||
var rad_pitch = Math.Radians(_Pitch)
|
||||
var camX = Math.Cos(rad_yaw) * Math.Cos(rad_pitch)
|
||||
var camY = Math.Sin(rad_pitch)
|
||||
var camZ = Math.Sin(rad_yaw) * Math.Cos(rad_pitch)
|
||||
|
||||
var newDir = Vector3.new(camX, camY, camZ)
|
||||
|
||||
cam.SetDirection(newDir)
|
||||
}
|
||||
|
||||
CheckInput() {
|
||||
|
||||
}
|
||||
|
||||
exit() {
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,16 @@
|
||||
class Math {
|
||||
foreign static Sqrt_(x, y, z)
|
||||
foreign static Sin(s)
|
||||
foreign static Cos(s)
|
||||
foreign static Radians(s)
|
||||
foreign static Degrees(s)
|
||||
|
||||
static Cross(vec1, vec2) {
|
||||
var result = this.Cross_(vec1.x, vec1.y, vec1.z, vec2.x, vec2.y, vec2.z)
|
||||
return Vector3.new(result[0], result[1], result[2])
|
||||
}
|
||||
|
||||
foreign static Cross_(x, y, z, x1, y2, z2)
|
||||
}
|
||||
|
||||
class Vector3 {
|
||||
@@ -7,6 +18,7 @@ class Vector3 {
|
||||
x {_x}
|
||||
y {_y}
|
||||
z {_z}
|
||||
|
||||
x=(value) {
|
||||
_x = value
|
||||
}
|
||||
@@ -49,6 +61,18 @@ class Vector3 {
|
||||
}
|
||||
}
|
||||
|
||||
-(other) {
|
||||
if(other is Vector3) {
|
||||
return Vector3.new(_x - other.x,
|
||||
_y - other.y,
|
||||
_z - other.z)
|
||||
} else if(other is Num) {
|
||||
return Vector3.new(_x - other,
|
||||
_y - other,
|
||||
_z - other)
|
||||
}
|
||||
}
|
||||
|
||||
construct new(x, y, z) {
|
||||
_x = x
|
||||
_y = y
|
||||
@@ -59,6 +83,10 @@ class Vector3 {
|
||||
return Math.Sqrt_(_x, _y, _z)
|
||||
}
|
||||
|
||||
Cross(vec) {
|
||||
Math.Cross(this, vec)
|
||||
}
|
||||
|
||||
Normalize() {
|
||||
var length = this.Sqrt()
|
||||
var x = _x / length
|
||||
|
||||
28
Editor/resources/Scripts/Physics.wren
Normal file
28
Editor/resources/Scripts/Physics.wren
Normal file
@@ -0,0 +1,28 @@
|
||||
import "Scripts/Math" for Vector3
|
||||
|
||||
class CollisionResult {
|
||||
|
||||
LocalPosition { _Local}
|
||||
WorldPosition { _World}
|
||||
Normal { _Normal}
|
||||
|
||||
construct new(l, w, n) {
|
||||
_Local = l
|
||||
_World = w
|
||||
_Normal = n
|
||||
}
|
||||
}
|
||||
|
||||
class Physics {
|
||||
foreign static Raycast_(x, y, z, x2, y2, z2)
|
||||
|
||||
static Raycast(v1, v2) {
|
||||
var result = this.Raycast_(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z)
|
||||
|
||||
var local = Vector3.new(result[0], result[1], result[2])
|
||||
var world = Vector3.new(result[3], result[4], result[5])
|
||||
var normal = Vector3.new(result[6], result[7], result[8])
|
||||
|
||||
return CollisionResult.new(local, world, normal)
|
||||
}
|
||||
}
|
||||
99
Editor/resources/Scripts/Player.wren
Normal file
99
Editor/resources/Scripts/Player.wren
Normal file
@@ -0,0 +1,99 @@
|
||||
import "Scripts/ScriptableEntity" for ScriptableEntity
|
||||
import "Scripts/Engine" for Engine
|
||||
import "Scripts/Scene" for Scene
|
||||
import "Scripts/Math" for Vector3
|
||||
import "Scripts/Input" for Input
|
||||
import "Scripts/Physics" for Physics, CollisionResult
|
||||
|
||||
class PlayerScript is ScriptableEntity {
|
||||
|
||||
construct new() {
|
||||
_InputDir = Vector3.new(0, 0, 0)
|
||||
_Velocity = Vector3.new(0, 0, 0)
|
||||
_Accel = 150
|
||||
_Deccel = 0.92
|
||||
_AirDeccel = 0.7
|
||||
_Gravity = 20
|
||||
|
||||
_MaxSpeed = 20
|
||||
_Jump = 800
|
||||
//Input.HideMouse()
|
||||
}
|
||||
|
||||
init() {
|
||||
Engine.Log("Player init")
|
||||
}
|
||||
|
||||
update(ts) {
|
||||
this.CheckInput()
|
||||
|
||||
var camEntity = Scene.GetEntity("Camera")
|
||||
var cam = camEntity.GetComponent("Camera")
|
||||
|
||||
var dir = cam.GetDirection()
|
||||
dir.y = 0
|
||||
dir = dir.Normalize()
|
||||
|
||||
var right = cam.GetRight()
|
||||
right.y = 0
|
||||
right = right.Normalize()
|
||||
var new_Velocity = (dir * _InputDir.z) + (right * _InputDir.x)
|
||||
|
||||
var controller = this.GetComponent("CharacterController")
|
||||
var transform = this.GetComponent("Transform")
|
||||
|
||||
|
||||
var from = transform.GetTranslation()
|
||||
var to = from - Vector3.new(0, 1, 0)
|
||||
|
||||
var normal = Physics.Raycast(from, to).Normal.Normalize()
|
||||
|
||||
Engine.Log("Normal col: (%(normal.x), %(normal.y), %(normal.z))")
|
||||
|
||||
if(!controller.IsOnGround()) {
|
||||
_Velocity.y = _Velocity.y - _Gravity
|
||||
//_Velocity.x = _Velocity.x * _AirDeccel
|
||||
//_Velocity.z = _Velocity.z * _AirDeccel
|
||||
} else {
|
||||
_Velocity.y = -20
|
||||
|
||||
if(Input.IsKeyPressed(32)) _Velocity.y = _Jump
|
||||
|
||||
|
||||
_Velocity.x = _Velocity.x + new_Velocity.x * _Accel
|
||||
_Velocity.z = _Velocity.z + new_Velocity.z * _Accel
|
||||
_Velocity.x = _Velocity.x * _Deccel
|
||||
_Velocity.z = _Velocity.z * _Deccel
|
||||
}
|
||||
controller.MoveAndSlide(_Velocity * ts)
|
||||
}
|
||||
|
||||
CheckInput() {
|
||||
/*
|
||||
87 = W
|
||||
65 = A
|
||||
83 = S
|
||||
68 = D
|
||||
32 = SPACE
|
||||
*/
|
||||
if(Input.IsKeyDown(87)) {
|
||||
_InputDir.z = 1
|
||||
} else if(Input.IsKeyDown(83)) {
|
||||
_InputDir.z = -1
|
||||
} else {
|
||||
_InputDir.z = 0
|
||||
}
|
||||
if(Input.IsKeyDown(65)) {
|
||||
_InputDir.x = 1
|
||||
} else if(Input.IsKeyDown(68)) {
|
||||
_InputDir.x = -1
|
||||
} else {
|
||||
_InputDir.x = 0
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
exit() {
|
||||
Engine.Log("Player exit")
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,8 @@ class Scene {
|
||||
return CharacterController.new(id)
|
||||
} else if (component == "Camera") {
|
||||
return Camera.new(id)
|
||||
} else if (component == "Transform") {
|
||||
return TransformComponent.new(id)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -32,6 +34,7 @@ class Scene {
|
||||
// Components
|
||||
//
|
||||
// Transform
|
||||
foreign static GetTranslation_(e)
|
||||
//foreign static SetTranslation_(e, x, y, z)
|
||||
//foreign static SetRotation_(e, x, y, z)
|
||||
//foreign static SetScale_(e, x, y, z)
|
||||
@@ -53,6 +56,7 @@ class Scene {
|
||||
|
||||
// Character controller
|
||||
foreign static MoveAndSlide_(e, x, y, z)
|
||||
foreign static IsCharacterControllerOnGround_(e)
|
||||
//foreign static IsOnGround_(e)
|
||||
|
||||
|
||||
@@ -97,6 +101,19 @@ class Entity {
|
||||
*/
|
||||
}
|
||||
|
||||
class TransformComponent {
|
||||
construct new(id) {
|
||||
_entityId = id
|
||||
}
|
||||
|
||||
GetTranslation() {
|
||||
var result = Scene.GetTranslation_(_entityId)
|
||||
return Vector3.new(result[0], result[1], result[2])
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class Light {
|
||||
construct new(id) {
|
||||
_entityId = id
|
||||
@@ -131,6 +148,10 @@ class CharacterController {
|
||||
MoveAndSlide(vel) {
|
||||
Scene.MoveAndSlide_(_entityId, vel.x, vel.y, vel.z)
|
||||
}
|
||||
|
||||
IsOnGround() {
|
||||
return Scene.IsCharacterControllerOnGround_(_entityId)
|
||||
}
|
||||
}
|
||||
|
||||
class Camera {
|
||||
|
||||
23
Editor/resources/Scripts/entityScript.wren
Normal file
23
Editor/resources/Scripts/entityScript.wren
Normal file
@@ -0,0 +1,23 @@
|
||||
import "Scripts/Engine" for Engine
|
||||
import "Scripts/ScriptableEntity" for ScriptableEntity
|
||||
|
||||
|
||||
class TestScript is ScriptableEntity {
|
||||
construct new() {
|
||||
_deltaTime = 0
|
||||
}
|
||||
|
||||
init() {
|
||||
Engine.Log("Hello init")
|
||||
}
|
||||
|
||||
update(ts) {
|
||||
_deltaTime = _deltaTime + ts
|
||||
|
||||
|
||||
}
|
||||
|
||||
exit() {
|
||||
Engine.Log("Hello exit")
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,23 @@
|
||||
import "Scripts/Engine" for Engine
|
||||
import "Scripts/Input" for Input
|
||||
import "Scripts/Scene" for Scene, Entity
|
||||
|
||||
class Test {
|
||||
construct new() {}
|
||||
|
||||
init() {
|
||||
System.print("hello init")
|
||||
}
|
||||
|
||||
update(t) {
|
||||
System.print("hello update %(t)")
|
||||
}
|
||||
|
||||
exit() {
|
||||
System.print("hello exit ")
|
||||
}
|
||||
|
||||
// Gets called on the click event.
|
||||
static hello() {
|
||||
// Get the entity named Light
|
||||
var entity = Scene.GetEntity("Light")
|
||||
var light = entity.GetComponent("Light")
|
||||
light.SetIntensity(1.0)
|
||||
|
||||
if(Input.IsMouseButtonPressed(2) == true) {
|
||||
Engine.Log("RIGHT CLICK!!!!!!")
|
||||
}
|
||||
// Get the component light
|
||||
var light = entity.GetComponent("Light")
|
||||
//light.SetIntensity(222.0) // Change intensity
|
||||
|
||||
var currentIntensity = light.GetIntensity() // Get new intensity
|
||||
Engine.Log("Current intensity %(currentIntensity)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"Description":"","Name":"", "DefaultScene":"Scenes/test.scene"}
|
||||
{"DefaultScene":"Scenes/test.scene","Description":"","Name":""}
|
||||
@@ -35,7 +35,7 @@ void EditorInterface::Init()
|
||||
ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
|
||||
ImGui::DockSpaceOverViewport(viewport, dockspace_flags);
|
||||
|
||||
this->filesystem = FileSystemUI();
|
||||
//this->filesystem = FileSystemUI();
|
||||
}
|
||||
|
||||
|
||||
@@ -854,7 +854,7 @@ void EditorInterface::DrawRessourceWindow()
|
||||
textureID = m_SelectedMaterial->m_Normal->GetID();
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image3"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec2(2,2), ImVec4(0,0,0,1), ImVec4(1, 1, 1, 1)))
|
||||
{
|
||||
std::string texture = FileDialog::OpenFile("*.png|*.jpg");
|
||||
std::string texture = FileDialog::OpenFile("*.png");
|
||||
if (texture != "")
|
||||
{
|
||||
m_SelectedMaterial->SetNormal(TextureManager::Get()->GetTexture(texture));
|
||||
@@ -1130,13 +1130,13 @@ void EditorInterface::Draw()
|
||||
DrawRessourceWindow();
|
||||
DrawViewport();
|
||||
DrawSceneTree();
|
||||
DrawFileSystem();
|
||||
DrawDirectoryExplorer();
|
||||
//DrawDirectoryExplorer();
|
||||
DrawEntityPropreties();
|
||||
DrawLogger();
|
||||
|
||||
// new stuff
|
||||
filesystem.Draw();
|
||||
filesystem.DrawDirectoryExplorer();
|
||||
|
||||
if(m_ShowImGuiDemo)
|
||||
ImGui::ShowDemoWindow();
|
||||
|
||||
@@ -9,7 +9,7 @@ class Material;
|
||||
class EditorInterface
|
||||
{
|
||||
private:
|
||||
FileSystemUI filesystem;
|
||||
FileSystemUI filesystem = FileSystemUI();
|
||||
Entity m_SelectedEntity;
|
||||
bool m_IsEntitySelected = false;
|
||||
bool m_DrawGrid = false;
|
||||
|
||||
@@ -34,7 +34,7 @@ void FileSystemUI::Draw()
|
||||
}
|
||||
if (open)
|
||||
{
|
||||
//EditorInterfaceDrawFiletree(rootDirectory);
|
||||
EditorInterfaceDrawFiletree(rootDirectory);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
@@ -88,6 +88,12 @@ void FileSystemUI::DrawDirectory(Ref<Directory> directory)
|
||||
std::string id = ICON_FA_FOLDER + std::string("##") + directory->name;
|
||||
if (ImGui::Button(id.c_str(), ImVec2(100, 100)))
|
||||
m_CurrentDirectory = directory;
|
||||
if (ImGui::BeginPopupContextWindow())
|
||||
{
|
||||
if (ImGui::MenuItem("Htest"));
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
ImGui::Text(directory->name.c_str());
|
||||
ImGui::PopFont();
|
||||
}
|
||||
@@ -199,6 +205,54 @@ void FileSystemUI::DrawDirectoryExplorer()
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (ImGui::BeginPopupContextItem("item context menu"))
|
||||
{
|
||||
float value;
|
||||
if (ImGui::Selectable("Set to zero")) value = 0.0f;
|
||||
if (ImGui::Selectable("Set to PI")) value = 3.1415f;
|
||||
ImGui::SetNextItemWidth(-1);
|
||||
ImGui::DragFloat("##Value", &value, 0.1f, 0.0f, 0.0f);
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
if (ImGui::BeginPopupContextWindow())
|
||||
{
|
||||
if (ImGui::Button("New Wren script"))
|
||||
{
|
||||
ImGui::OpenPopup("CreateNewFile");
|
||||
|
||||
}
|
||||
if (ImGui::MenuItem("New interface script"))
|
||||
{
|
||||
}
|
||||
if (ImGui::MenuItem("New Scene"))
|
||||
{
|
||||
}
|
||||
if (ImGui::MenuItem("New folder"))
|
||||
{
|
||||
}
|
||||
if (ImGui::MenuItem("New interface"))
|
||||
{
|
||||
}
|
||||
if (ImGui::MenuItem("New stylesheet"))
|
||||
{
|
||||
}
|
||||
if (ImGui::BeginPopup("CreateNewFile"))
|
||||
{
|
||||
static char name[32] = "Label1";
|
||||
char buf[64];
|
||||
sprintf(buf, "Button: %s###Button", name); // ### operator override ID ignoring the preceding label
|
||||
|
||||
ImGui::Text("Edit name:");
|
||||
ImGui::InputText("##edit", name, IM_ARRAYSIZE(name));
|
||||
if (ImGui::Button("Close"))
|
||||
ImGui::CloseCurrentPopup();
|
||||
if(ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Enter)))
|
||||
ImGui::CloseCurrentPopup();
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
@@ -7,6 +7,22 @@
|
||||
#include "src/Scripting/ScriptLoader.h"
|
||||
#include "src/Core/Logger.h"
|
||||
|
||||
/* TODOS:
|
||||
*
|
||||
* Engine:
|
||||
* Trigger zones from trenchbroom
|
||||
* Scripting API vectors operation
|
||||
* Scripting API for all component
|
||||
* Scripting API for editing UI maybe
|
||||
* Launch game standalone
|
||||
* Fix physics system
|
||||
* trenchbroom physics element
|
||||
*
|
||||
* Editor:
|
||||
* File browser refact
|
||||
*
|
||||
*/
|
||||
|
||||
class Engine {
|
||||
private:
|
||||
static float m_LastFrameTime;
|
||||
|
||||
@@ -99,7 +99,7 @@ void FileSystem::Scan()
|
||||
RootDirectory = CreateRef<Directory>();
|
||||
RootDirectory->Files = std::vector<Ref<File>>();
|
||||
RootDirectory->Directories = std::vector<Ref<Directory>>();
|
||||
RootDirectory->name = Root;
|
||||
RootDirectory->name = FileSystem::AbsoluteToRelative(Root);
|
||||
RootDirectory->fullPath = Root;
|
||||
ScanDirectory(RootDirectory);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ bool Input::IsKeyPressed(int keycode)
|
||||
bool result = state == GLFW_PRESS;
|
||||
|
||||
// First time pressed?
|
||||
if (m_Keys.find(keycode) == m_Keys.end() || m_Keys[keycode] == false)
|
||||
if (m_Keys.find(keycode) == m_Keys.end() || m_Keys[keycode] == true)
|
||||
{
|
||||
if (result)
|
||||
m_Keys[keycode] = true;
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Physics
|
||||
}
|
||||
};
|
||||
|
||||
CharacterController::CharacterController(float height, float radius, float mass)
|
||||
CharacterController::CharacterController(float height, float radius, float mass, Vector3 position)
|
||||
{
|
||||
m_surfaceHitNormals = std::vector<glm::vec3>();
|
||||
|
||||
@@ -35,12 +35,12 @@ namespace Physics
|
||||
|
||||
btQuaternion quat = btQuaternion(0, 0, 0);
|
||||
m_Transform = new btTransform();
|
||||
m_Transform->setOrigin(btVector3(0.0f, 10.0f, 0.0f));
|
||||
m_Transform->setOrigin(btVector3(position.x, position.y, position.z));
|
||||
m_Transform->setRotation(quat);
|
||||
m_MotionState = new btDefaultMotionState(*m_Transform);
|
||||
|
||||
|
||||
btVector3 inertia;
|
||||
m_CollisionShape->calculateLocalInertia(mass, inertia);
|
||||
//m_CollisionShape->calculateLocalInertia(mass, inertia);
|
||||
|
||||
btRigidBody::btRigidBodyConstructionInfo rigidBodyCI(mass, m_MotionState, m_CollisionShape, inertia);
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace Physics
|
||||
|
||||
rigidBodyCI.m_linearDamping = 0.0f;
|
||||
m_Rigidbody = new btRigidBody(rigidBodyCI);
|
||||
|
||||
m_Rigidbody->setGravity(btVector3(0, 0, 0));
|
||||
// Keep upright
|
||||
m_Rigidbody->setAngularFactor(0.0f);
|
||||
|
||||
@@ -71,6 +71,7 @@ namespace Physics
|
||||
|
||||
void CharacterController::MoveAndSlide(glm::vec3 velocity)
|
||||
{
|
||||
m_Rigidbody->setGravity(btVector3(0, 0, 0));
|
||||
m_manualVelocity = velocity;
|
||||
// Sync ghost with actually object
|
||||
m_GhostObject->setWorldTransform(m_Rigidbody->getWorldTransform());
|
||||
@@ -162,7 +163,7 @@ namespace Physics
|
||||
|
||||
m_Rigidbody->setLinearVelocity(vel);
|
||||
|
||||
m_onGround = true;
|
||||
IsOnGround = true;
|
||||
}
|
||||
|
||||
float testOffset = 0.07f;
|
||||
@@ -189,8 +190,8 @@ namespace Physics
|
||||
|
||||
void CharacterController::UpdateVelocity()
|
||||
{
|
||||
m_manualVelocity.y = m_Rigidbody->getLinearVelocity().getY();
|
||||
|
||||
//m_manualVelocity.y = m_Rigidbody->getLinearVelocity().getY();
|
||||
btVector3 grav = m_Rigidbody->getGravity();
|
||||
btVector3 finalVel = btVector3(m_manualVelocity.x, m_manualVelocity.y, m_manualVelocity.z);
|
||||
m_Rigidbody->setLinearVelocity(finalVel);
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <BulletCollision/CollisionDispatch/btGhostObject.h>
|
||||
#include <vector>
|
||||
#include "../Core/Maths.h"
|
||||
namespace Physics
|
||||
{
|
||||
class CharacterController
|
||||
@@ -12,14 +13,14 @@ namespace Physics
|
||||
public:
|
||||
bool IsOnGround = false;
|
||||
bool m_hittingWall;
|
||||
float m_stepHeight = 0.05f;
|
||||
float m_stepHeight = .1f;
|
||||
|
||||
btTransform* m_Transform;
|
||||
btCollisionShape* m_CollisionShape;
|
||||
btRigidBody* m_Rigidbody;
|
||||
btPairCachingGhostObject* m_GhostObject;
|
||||
btMotionState* m_MotionState;
|
||||
bool m_onGround;
|
||||
|
||||
//bool m_onJumpableGround; // A bit lower contact than just onGround
|
||||
|
||||
float m_bottomYOffset;
|
||||
@@ -33,7 +34,7 @@ namespace Physics
|
||||
btVector3 m_previousPosition;
|
||||
|
||||
float m_jumpRechargeTimer;
|
||||
CharacterController(float height, float radius, float mass);
|
||||
CharacterController(float height, float radius, float mass, Vector3 position);
|
||||
|
||||
void MoveAndSlide(glm::vec3 velocity);
|
||||
private:
|
||||
|
||||
@@ -21,6 +21,8 @@ namespace Physics
|
||||
dynamicsWorld->setDebugDrawer(new BulletDebugDrawer());
|
||||
|
||||
m_Bodies = std::map<btRigidBody*, Ref<RigidBody>>();
|
||||
|
||||
SetGravity(Vector3(0, -10000, 0));
|
||||
}
|
||||
|
||||
|
||||
@@ -58,12 +60,18 @@ namespace Physics
|
||||
btCollisionWorld::ClosestRayResultCallback res(btFrom, btTo);
|
||||
|
||||
dynamicsWorld->rayTest(btFrom, btTo, res);
|
||||
|
||||
btVector3 localNormal;
|
||||
if(res.m_collisionObject)
|
||||
{
|
||||
// TODO: Fix the godammn fucked up normal
|
||||
localNormal = res.m_collisionObject->getWorldTransform().getBasis().inverse() * res.m_hitNormalWorld;
|
||||
}
|
||||
|
||||
// Map bullet result to dto.
|
||||
RaycastResult result{
|
||||
glm::vec3(res.m_hitPointWorld.x(), res.m_hitPointWorld.y(), res.m_hitPointWorld.z()),
|
||||
glm::vec3(res.m_hitPointWorld.x(), res.m_hitPointWorld.y(), res.m_hitPointWorld.z()),
|
||||
glm::vec3(res.m_hitNormalWorld.x(), res.m_hitNormalWorld.y(), res.m_hitNormalWorld.z())
|
||||
glm::vec3(localNormal.x(), localNormal.y(), localNormal.z())
|
||||
};
|
||||
|
||||
return result;
|
||||
|
||||
@@ -15,6 +15,21 @@ public:
|
||||
|
||||
}
|
||||
|
||||
json Serialize() {
|
||||
BEGIN_SERIALIZE();
|
||||
SERIALIZE_VAL(Height);
|
||||
SERIALIZE_VAL(Radius);
|
||||
SERIALIZE_VAL(Mass);
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool Deserialize(const std::string str) {
|
||||
BEGIN_DESERIALIZE();
|
||||
Height = j["Height"];
|
||||
Radius = j["Radius"];
|
||||
Mass = j["Mass"];
|
||||
return true;
|
||||
}
|
||||
void SyncWithTransform(TransformComponent& tc)
|
||||
{
|
||||
btVector3 pos = CharacterController->m_motionTransform.getOrigin();
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
class NameComponent {
|
||||
public:
|
||||
std::string Name = "Entity";
|
||||
|
||||
int Id;
|
||||
json Serialize()
|
||||
{
|
||||
BEGIN_SERIALIZE();
|
||||
|
||||
@@ -19,6 +19,7 @@ struct ParentComponent
|
||||
|
||||
bool Deserialize(std::string str)
|
||||
{
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@@ -78,9 +78,9 @@ void QuakeMapComponent::Build()
|
||||
vertex_uv vertex_uv = get_standard_uv(vertex.vertex, face, texture->width, texture->height);
|
||||
vertices.push_back(Vertex{
|
||||
glm::vec3(vertex.vertex.y * (1.0f / 64), vertex.vertex.z * (1.0f / 64), vertex.vertex.x * (1.0f / 64)),
|
||||
glm::vec2(vertex_uv.u, vertex_uv.v),
|
||||
glm::vec3(vertex.normal.x, vertex.normal.z, vertex.normal.y),
|
||||
glm::vec3(vertex.tangent.x, vertex.tangent.z, vertex.tangent.y), glm::vec3(0.0, 1.0, 0.0), 0.0f
|
||||
glm::vec2(vertex_uv.u, 1.0 -vertex_uv.v),
|
||||
glm::vec3(vertex.normal.y, vertex.normal.z, vertex.normal.x),
|
||||
glm::vec3(vertex.tangent.y, vertex.tangent.z, vertex.tangent.x), glm::vec3(0.0, 1.0, 0.0), 0.0f
|
||||
});
|
||||
|
||||
//printf("vertex: (%f %f %f), normal: (%f %f %f)\n",
|
||||
|
||||
@@ -32,6 +32,7 @@ public:
|
||||
{
|
||||
BEGIN_DESERIALIZE();
|
||||
this->Path = j["Path"];
|
||||
this->HasCollisions = j["HasCollisions"];
|
||||
Build(); // Maybe have some kind of loading bar or something.
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "Components/LightComponent.h"
|
||||
#include "Components/QuakeMap.h"
|
||||
#include <src/Scene/Entities/Components/WrenScriptComponent.h>
|
||||
#include <src/Scene/Entities/Components/CharacterControllerComponent.h>
|
||||
void Entity::AddChild(Entity ent)
|
||||
{
|
||||
if ((int)m_EntityHandle != ent.GetHandle())
|
||||
@@ -34,6 +35,8 @@ json Entity::Serialize()
|
||||
SERIALIZE_OBJECT_REF_LBL("LightComponent", GetComponent<LightComponent>());
|
||||
if (HasComponent<WrenScriptComponent>())
|
||||
SERIALIZE_OBJECT_REF_LBL("WrenScriptComponent", GetComponent<WrenScriptComponent>());
|
||||
if (HasComponent<CharacterControllerComponent>())
|
||||
SERIALIZE_OBJECT_REF_LBL("CharacterControllerComponent", GetComponent<CharacterControllerComponent>());
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
@@ -47,6 +50,7 @@ bool Entity::Deserialize(const std::string& str)
|
||||
DESERIALIZE_COMPONENT(QuakeMapComponent);
|
||||
DESERIALIZE_COMPONENT(LightComponent);
|
||||
DESERIALIZE_COMPONENT(WrenScriptComponent);
|
||||
DESERIALIZE_COMPONENT(CharacterControllerComponent);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ void Scene::OnInit()
|
||||
{
|
||||
auto [transform, cc] = ccview.get<TransformComponent, CharacterControllerComponent>(e);
|
||||
|
||||
cc.CharacterController = CreateRef<Physics::CharacterController>(cc.Height, cc.Radius, cc.Mass);
|
||||
cc.CharacterController = CreateRef<Physics::CharacterController>(cc.Height, cc.Radius, cc.Mass, transform.Translation);
|
||||
Entity ent = Entity({ e, this });
|
||||
|
||||
PhysicsManager::Get()->RegisterCharacterController(cc.CharacterController);
|
||||
@@ -325,7 +325,7 @@ void Scene::Draw()
|
||||
}
|
||||
|
||||
Renderer::m_Shader->Bind();
|
||||
|
||||
Renderer::m_Shader->SetUniform3f("u_EyePosition", cam->GetTranslation().x, cam->GetTranslation().y, cam->GetTranslation().z);
|
||||
Renderer::m_Shader->SetUniform1i("u_ShowNormal", 0);
|
||||
if (cam)
|
||||
{
|
||||
@@ -348,6 +348,8 @@ void Scene::Draw()
|
||||
|
||||
copyT.Translation = globalOffset;
|
||||
}
|
||||
|
||||
|
||||
Renderer::m_Shader->SetUniformMat4f("u_View", cam->GetTransform());
|
||||
Renderer::m_Shader->SetUniformMat4f("u_Projection", cam->GetPerspective());
|
||||
Renderer::m_Shader->SetUniformMat4f("u_Model", copyT.GetTransform());
|
||||
@@ -433,7 +435,7 @@ void Scene::EditorDraw()
|
||||
if (m_EditorCamera)
|
||||
{
|
||||
Renderer::m_Shader->SetUniform1f("u_Exposure", m_EditorCamera->Exposure);
|
||||
|
||||
Renderer::m_Shader->SetUniform3f("u_EyePosition", m_EditorCamera->GetTranslation().x, m_EditorCamera->GetTranslation().y, m_EditorCamera->GetTranslation().z);
|
||||
auto view = m_Registry.view<TransformComponent, ModelComponent, ParentComponent>();
|
||||
for (auto e : view) {
|
||||
auto [transform, model, parent] = view.get<TransformComponent, ModelComponent, ParentComponent>(e);
|
||||
|
||||
@@ -22,7 +22,11 @@ namespace ScriptAPI
|
||||
void RegisterModule(WrenVM* vm) override
|
||||
{
|
||||
RegisterMethod("Sqrt_(_,_,_)", (void*)Sqrt);
|
||||
|
||||
RegisterMethod("Sin(_)", (void*)Sin);
|
||||
RegisterMethod("Cos(_)", (void*)Cos);
|
||||
RegisterMethod("Radians(_)", (void*)Radians);
|
||||
RegisterMethod("Degrees(_)", (void*)Degrees);
|
||||
RegisterMethod("Cross_(_,_,_,_,_,_)", (void*)Cross);
|
||||
}
|
||||
|
||||
static void Sqrt(WrenVM* vm)
|
||||
@@ -33,6 +37,55 @@ namespace ScriptAPI
|
||||
float result = glm::sqrt((x * x) + (y * y) + (z * z));
|
||||
wrenSetSlotDouble(vm, 0, result);
|
||||
}
|
||||
|
||||
static void Cos(WrenVM* vm)
|
||||
{
|
||||
float d = wrenGetSlotDouble(vm, 1);
|
||||
float result = glm::cos(d);
|
||||
wrenSetSlotDouble(vm, 0, result);
|
||||
}
|
||||
|
||||
static void Sin(WrenVM* vm)
|
||||
{
|
||||
float d = wrenGetSlotDouble(vm, 1);
|
||||
float result = glm::sin(d);
|
||||
wrenSetSlotDouble(vm, 0, result);
|
||||
}
|
||||
|
||||
static void Radians(WrenVM* vm)
|
||||
{
|
||||
float d = wrenGetSlotDouble(vm, 1);
|
||||
float result = glm::radians(d);
|
||||
wrenSetSlotDouble(vm, 0, result);
|
||||
}
|
||||
|
||||
static void Degrees(WrenVM* vm)
|
||||
{
|
||||
float d = wrenGetSlotDouble(vm, 1);
|
||||
float result = glm::degrees(d);
|
||||
wrenSetSlotDouble(vm, 0, result);
|
||||
}
|
||||
|
||||
static void Cross(WrenVM* vm)
|
||||
{
|
||||
Vector3 v1 = Vector3(wrenGetSlotDouble(vm, 1),
|
||||
wrenGetSlotDouble(vm, 2),
|
||||
wrenGetSlotDouble(vm, 3));
|
||||
Vector3 v2 = Vector3(wrenGetSlotDouble(vm, 4),
|
||||
wrenGetSlotDouble(vm, 5),
|
||||
wrenGetSlotDouble(vm, 6));
|
||||
Vector3 cross = glm::cross(v1, v2);
|
||||
|
||||
|
||||
wrenSetSlotNewList(vm, 0);
|
||||
wrenSetSlotDouble(vm, 1, cross.x);
|
||||
wrenSetSlotDouble(vm, 2, cross.y);
|
||||
wrenSetSlotDouble(vm, 3, cross.z);
|
||||
|
||||
wrenInsertInList(vm, 0, -1, 1);
|
||||
wrenInsertInList(vm, 0, -1, 2);
|
||||
wrenInsertInList(vm, 0, -1, 3);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
63
Nuake/src/Scripting/Modules/PhysicsModule.h
Normal file
63
Nuake/src/Scripting/Modules/PhysicsModule.h
Normal file
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
#include "wren.h"
|
||||
#include <string>
|
||||
#include <src/Core/Logger.h>
|
||||
#include "../Core/Maths.h"
|
||||
#include "ScriptModule.h"
|
||||
#include <iostream>
|
||||
#include <wren.h>
|
||||
#include "../Core/Physics/PhysicsManager.h"
|
||||
namespace ScriptAPI
|
||||
{
|
||||
class PhysicsModule : public ScriptModule
|
||||
{
|
||||
std::string ModuleName = "Engine";
|
||||
|
||||
std::string GetModuleName() override
|
||||
{
|
||||
return "Physics";
|
||||
}
|
||||
|
||||
void RegisterModule(WrenVM* vm) override
|
||||
{
|
||||
RegisterMethod("Raycast_(_,_,_,_,_,_)", (void*)Raycast);
|
||||
}
|
||||
|
||||
static void Raycast(WrenVM* vm)
|
||||
{
|
||||
Vector3 v1 = Vector3(wrenGetSlotDouble(vm, 1),
|
||||
wrenGetSlotDouble(vm, 2),
|
||||
wrenGetSlotDouble(vm, 3));
|
||||
Vector3 v2 = Vector3(wrenGetSlotDouble(vm, 4),
|
||||
wrenGetSlotDouble(vm, 5),
|
||||
wrenGetSlotDouble(vm, 6));
|
||||
|
||||
RaycastResult result = PhysicsManager::Get()->Raycast(v1, v2);
|
||||
wrenSetSlotNewList(vm, 0);
|
||||
|
||||
// Returns a list with 3 vectors placed sequentially
|
||||
// should be reconstructed in the wren side.
|
||||
wrenSetSlotDouble(vm, 1, result.LocalPoint.x);
|
||||
wrenSetSlotDouble(vm, 2, result.LocalPoint.y);
|
||||
wrenSetSlotDouble(vm, 3, result.LocalPoint.z);
|
||||
|
||||
wrenSetSlotDouble(vm, 4, result.WorldPoint.x);
|
||||
wrenSetSlotDouble(vm, 5, result.WorldPoint.y);
|
||||
wrenSetSlotDouble(vm, 6, result.WorldPoint.z);
|
||||
|
||||
wrenSetSlotDouble(vm, 7, result.Normal.x - result.WorldPoint.x);
|
||||
wrenSetSlotDouble(vm, 8, result.Normal.y - result.WorldPoint.y);
|
||||
wrenSetSlotDouble(vm, 9, result.Normal.z - result.WorldPoint.z);
|
||||
|
||||
wrenInsertInList(vm, 0, -1, 1);
|
||||
wrenInsertInList(vm, 0, -1, 2);
|
||||
wrenInsertInList(vm, 0, -1, 3);
|
||||
wrenInsertInList(vm, 0, -1, 4);
|
||||
wrenInsertInList(vm, 0, -1, 5);
|
||||
wrenInsertInList(vm, 0, -1, 6);
|
||||
wrenInsertInList(vm, 0, -1, 7);
|
||||
wrenInsertInList(vm, 0, -1, 8);
|
||||
wrenInsertInList(vm, 0, -1, 9);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -29,12 +29,14 @@ namespace ScriptAPI
|
||||
{
|
||||
RegisterMethod("GetEntityID(_)", (void*)GetEntity);
|
||||
RegisterMethod("EntityHasComponent(_,_)", (void*)EntityHasComponent);
|
||||
RegisterMethod("GetTranslation_(_)", (void*)GetTranslation);
|
||||
RegisterMethod("SetLightIntensity_(_,_)", (void*)SetLightIntensity);
|
||||
RegisterMethod("GetLightIntensity_(_)", (void*)GetLightIntensity);
|
||||
RegisterMethod("SetCameraDirection_(_,_,_,_)", (void*)SetCameraDirection);
|
||||
RegisterMethod("GetCameraDirection_(_)", (void*)GetCameraDirection);
|
||||
RegisterMethod("GetCameraRight_(_)", (void*)GetCameraRight);
|
||||
RegisterMethod("MoveAndSlide_(_,_,_,_)", (void*)MoveAndSlide);
|
||||
RegisterMethod("IsCharacterControllerOnGround_(_)", (void*)IsCharacterControllerOnGround);
|
||||
}
|
||||
|
||||
static void GetEntity(WrenVM* vm)
|
||||
@@ -158,7 +160,14 @@ namespace ScriptAPI
|
||||
wrenInsertInList(vm, 0, 2, 3);
|
||||
}
|
||||
|
||||
|
||||
static void IsCharacterControllerOnGround(WrenVM* vm)
|
||||
{
|
||||
int handle = wrenGetSlotDouble(vm, 1);
|
||||
Entity ent = Entity((entt::entity)handle, Engine::GetCurrentScene().get());
|
||||
auto& characterController = ent.GetComponent<CharacterControllerComponent>();
|
||||
bool result = characterController.CharacterController->IsOnGround;
|
||||
wrenSetSlotBool(vm, 0, result);
|
||||
}
|
||||
|
||||
static void MoveAndSlide(WrenVM* vm)
|
||||
{
|
||||
@@ -172,5 +181,22 @@ namespace ScriptAPI
|
||||
characterController.CharacterController->MoveAndSlide(Vector3(x, y, z));
|
||||
}
|
||||
|
||||
static void GetTranslation(WrenVM* vm)
|
||||
{
|
||||
int handle = wrenGetSlotDouble(vm, 1);
|
||||
Entity ent = Entity((entt::entity)handle, Engine::GetCurrentScene().get());
|
||||
auto& transform = ent.GetComponent<TransformComponent>();
|
||||
// set the slots
|
||||
wrenSetSlotDouble(vm, 1, transform.Translation.x);
|
||||
wrenSetSlotDouble(vm, 2, transform.Translation.y);
|
||||
wrenSetSlotDouble(vm, 3, transform.Translation.z);
|
||||
|
||||
// Fill the list
|
||||
wrenSetSlotNewList(vm, 0);
|
||||
wrenInsertInList(vm, 0, 0, 1);
|
||||
wrenInsertInList(vm, 0, 1, 2);
|
||||
wrenInsertInList(vm, 0, 2, 3);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <src/Scripting/Modules/SceneModule.h>
|
||||
#include <src/Scripting/Modules/MathModule.h>
|
||||
#include <src/Scripting/Modules/InputModule.h>
|
||||
#include <src/Scripting/Modules/PhysicsModule.h>
|
||||
|
||||
WrenVM* ScriptingEngine::m_WrenVM;
|
||||
|
||||
@@ -112,6 +113,8 @@ void ScriptingEngine::Init()
|
||||
RegisterModule(mathModule);
|
||||
Ref<ScriptAPI::InputModule> inputModule = CreateRef<ScriptAPI::InputModule> ();
|
||||
RegisterModule(inputModule);
|
||||
Ref<ScriptAPI::PhysicsModule> physicsModule = CreateRef<ScriptAPI::PhysicsModule>();
|
||||
RegisterModule(physicsModule);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -153,7 +153,8 @@ int Window::Init()
|
||||
// TODO: Style should move to editor
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontDefault();
|
||||
io.Fonts->AddFontFromFileTTF("resources/Fonts/OpenSans-Regular.ttf", 16.0);
|
||||
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
|
||||
ImGui::StyleColorsDark();
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ After attaching the WrenScript component on an entity, you can select the script
|
||||
In addition to pointing to the script file, you need to specify which class in the script is considered as the
|
||||
entity script.
|
||||
|
||||
The class chosen must inherite from ScriptableEntity.
|
||||
The class chosen must inherit from ScriptableEntity.
|
||||
|
||||
Here is an example of a barebone entity scripts::
|
||||
|
||||
@@ -16,13 +16,15 @@ Here is an example of a barebone entity scripts::
|
||||
class TestScript is ScriptableEntity {
|
||||
construct new() {
|
||||
}
|
||||
|
||||
|
||||
init() {
|
||||
|
||||
}
|
||||
|
||||
update(ts) {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
exit() {
|
||||
|
||||
Reference in New Issue
Block a user