NOWA-Design

A place to show off your latest screenshots and for people to comment on them. Only start a new thread here if you have some nice images to show off!
Post Reply
Lax
Gnome
Posts: 322
Joined: Mon Aug 06, 2007 12:53 pm
Location: Saarland, Germany
x 7

NOWA-Design

Post by Lax » Mon Apr 30, 2018 5:58 pm

Hi folks,

just wanted to present the NOWA-Design editor on which I work heavily, using newest Ogre 2.1 technologies.

Note: There is still a lot of work todo, but I'm only programming in my spare time, which is a small time window.
My dream is to create a complex MetroidVania game, with inventory, shop system, and lot of game mechanics.

The NOWA-Design editor is in an early creation stage and uses the NOWA-Engine intensively. The editor can be used to create complex virtual environments. The speciality is its ability to simulate everything at runtime. The user may create a world add some GameObjects arm the GameObjects with some components to obtain some abilities like physics behaviors or particle effects, sounds etc. When the user presses the “Play” button. Everything will be rendered in realtime and the user may interact with the GameObjects. By pressing the “Stop” button everything will be placed in an “undo”-step to its stage before the simulation has happened. The biggest feature is that the LuaScriptComponent, that can be used for any game object, adding custom behavior at runtime, which is demonstrated in the video below "NOWA Design LuaScript AreaOfInterest".

The NOWA-Design editor has a lot of functionalities. Some will be listed below:

Ogre2.1 workspace management to create and change workspaces for “Physically Based Shading” (PBS), skies and sky-reflections at realtime
  • Full integrated undo/redo functionality
  • Camera position/orientation undo/redo functionality
  • GameObject selection undo/redo functionality
  • Gizmo in order to help transform GameObjects
  • Several GameObject place modes like stacking and orientated stacking
  • Creation of GameObject-groups and store them. So that complex scenarios can be created bit by bit
  • Tons of components which can be added to GameObjects and activated
  • Interface for Lua scripting and on the fly activation of the scripts
  • Recast pathfinding integration
  • Terra integration
Some videos:
[flash=][/flash]
[flash=][/flash]
[flash=][/flash]
[flash=][/flash]
[flash=][/flash]
[flash=][/flash]
[flash=][/flash]
[flash=][/flash]
[flash=][/flash]
[flash=][/flash]

Other feature videos will follow...

Source code available here:
https://sourceforge.net/projects/nowa-engine/

Homepage with more information:
http://www.lukas-kalinowski.com/Homepage/?page_id=23

Regards
Lax
2 x

Lax
Gnome
Posts: 322
Joined: Mon Aug 06, 2007 12:53 pm
Location: Saarland, Germany
x 7

Re: NOWA-Design

Post by Lax » Wed Mar 06, 2019 8:37 pm

Hi,

I was busy with the NOWA-Engine all the time and I thought, why not posting some new features :)

I created a 2,5 Jump'N'Run test scenario in NOWA-Design with ragdoll activation on the fly. The whole character movement is completely implemented in lua script and can be changed at runtime.



Here a snippet the lua script:

Code: Select all

module("PrehistoricLax_0", package.seeall);

-- Enums
NONE, UP, DOWN, LEFT, RIGHT = 0, 1, 2, 3, 4

playerController = nil;
backgroundMusic = nil;
walkSound = nil;
jumpSound = nil;
smokeParticle = nil;
animationBlender = nil;
characterSliderMaterial = nil;
leftFoot = nil;
rightFoot = nil;
leftFootOriginOrientation = nil;
rightFootOriginOrientation = nil;

directionMove = Vector3.ZERO;
direction = NONE;
directionChanged = false;
oldDirection = NONE;
isJumping = false;
boringTimer = 5;
noMoveTimer = 0;
jumpForce = 0;
inAir = false;
isAttacking = false;
tryJump = false;
highFalling = false;
jumpKeyPressed = false;
jumpCount = 0;
canDoubleJump = false;
walkCount = 0;
isOnRope = false;
groundedOnce = true;
duckedOnce = false;
acceleration = 0.5;
oldPositionY = 0;
relativeHeight = 0;

 -- later control double jump via attributes component
doubleJump = true;
runAfterWalkTime = 3; 

timeSinceLastPush = 1;
canPush = true;

PrehistoricLax_0 = {};

PrehistoricLax_0["connect"] = function(gameObject)
	 local mainGameObject = GameObjectController:getGameObjectFromId(MAIN_GAMEOBJECT_ID);
	 backgroundMusic = mainGameObject:getSimpleSoundComponent(0);
	 backgroundMusic:setActivated(true);
	 timeSinceLastPush = 1;
end

PrehistoricLax_0["disconnect"] = function(gameObject)
	 backgroundMusic:setActivated(false);
	 gameObject:getPlayerController():getPhysicsRagDollComponent():setState("Inactive");
end

WalkState = { };

WalkState["enter"] = function(gameObject)
	 playerController = gameObject:getPlayerControllerJumpNRunLuaComponent();
	 walkSound = playerController:getOwner():getSimpleSoundComponent(0);
	 jumpSound = playerController:getOwner():getSimpleSoundComponent(1);
	 smokeParticle = playerController:getOwner():getParticleUniverseComponent(0);
	 smokeParticle:setActivated(false);
	 --smokeParticle:setPlaySpeed(10);
	 smokeParticle:setPlayTimeMS(50);
	 --smokeParticle:setScale(Vector3(0.05, 0.05, 0.05));
	 walkSound:setActivated(false);
	 jumpSound:setActivated(false);
	 walkSound:setPitch(0.65);
	 walkSound:setVolume(15);
	 jumpSound:setVolume(50);
	 
	 animationBlender = playerController:getAnimationBlender();
	 local mainGameObject = GameObjectController:getGameObjectFromId(MAIN_GAMEOBJECT_ID);
	 characterSliderMaterial = mainGameObject:getPhysicsMaterialComponent(2);
	 
	 if (animationBlender ~= nil) then
		log("enter: animationBlender ok");
	 else
		log("enter: animationBlender nil");
	 end
	 animationBlender:registerAnimation(AnimationBlender.ANIM_IDLE_1, "Idle");
	 animationBlender:registerAnimation(AnimationBlender.ANIM_IDLE_2, "Greet");
	 animationBlender:registerAnimation(AnimationBlender.ANIM_IDLE_3, "Bored");
	 animationBlender:registerAnimation(AnimationBlender.ANIM_WALK_NORTH, "Walk");
	 animationBlender:registerAnimation(AnimationBlender.ANIM_WALK_SOUTH, "Walk_backwards");
	 animationBlender:registerAnimation(AnimationBlender.ANIM_WALK_WEST, "Walk");
	 animationBlender:registerAnimation(AnimationBlender.ANIM_WALK_EAST, "Walk");
	 animationBlender:registerAnimation(AnimationBlender.ANIM_JUMP_START, "Jump2");
	 animationBlender:registerAnimation(AnimationBlender.ANIM_JUMP_WALK, "Jump");
	 animationBlender:registerAnimation(AnimationBlender.ANIM_HIGH_JUMP_END, "Land");
	 animationBlender:registerAnimation(AnimationBlender.ANIM_JUMP_END, "Land2");
	 animationBlender:registerAnimation(AnimationBlender.ANIM_FALL, "Falling");
	 animationBlender:registerAnimation(AnimationBlender.ANIM_RUN, "Run");
	 animationBlender:registerAnimation(AnimationBlender.ANIM_SNEAK, "Take_damage");
	 animationBlender:registerAnimation(AnimationBlender.ANIM_DUCK, "Land2");
	 animationBlender:registerAnimation(AnimationBlender.ANIM_HALT, "Halt");
	 animationBlender:init(AnimationBlender.ANIM_IDLE_1, true);
	
	 boringTimer = 0;
	 noMoveTimer = 0;
	 jumpForce = 15;
end

WalkState["execute"] = function(gameObject, dt)
	
	if (noMoveTimer > 0.1) then
		playerController:setMoveWeight(0);
		playerController:setJumpWeight(0);
		noMoveTimer = noMoveTimer - dt;
	elseif (noMoveTimer < 0.1) then
		-- Call this only once, hence noMoveTimer = 0.1
		playerController:setMoveWeight(1);
		playerController:setJumpWeight(1);
		noMoveTimer = 0.1;
	end
	
	local tempSpeed = 0;
	local tempAnimationSpeed = playerController:getAnimationSpeed();
	local heading = playerController:getOrientation():getYaw();
	local height = playerController:getHeight();
	local onSlider = false;
	local onTrampolin = false;
	local atObstacle = false;
	local keyDirection = Vector3.ZERO;
	directionMove = Vector3.ZERO;
	
	if (height <= 0) then
		inAir = true;
	else
		inAir = height > 0.4;
	end

	-- Store the old direction, the check later whether a direction changed or not
	oldDirection = direction;
	-- Store the old position y, to check later the relative height
	if (inAir == false) then
		oldPositionY = playerController:getPhysicsComponent():getPosition().y;
	end
	relativeHeight = playerController:getPhysicsComponent():getPosition().y - oldPositionY;
	
	-- Set omega by default directly to zero, else there is an ugly small rotation...
	playerController:getPhysicsComponent():applyAngularImpulse(Vector3.ZERO);
	
	--log("In air: " .. (inAir and 'true' or 'false')); -- inAir is bool and somehow cannot be printed
	--log("Height: " .. height);
	--log("RelativeHeight: " .. relativeHeight);
	 
	------------------------------------------Ray Checks----------------------------------------------------
	-- Check what is below the player
	local hitGameObjectBelow = playerController:getHitGameObjectBelow();
	if (hitGameObjectBelow ~= nil) then
		if (hitGameObjectBelow:getCategory() == "Slider") then
			if (inAir == false) then
				onSlider = true;
				local horizontalSlider = hitGameObjectBelow:getJointActiveSliderComponent();
				if (horizontalSlider:getPin().x == 1) then
					directionMove = horizontalSlider:getPin() * horizontalSlider:getCurrentDirection() * horizontalSlider:getMoveSpeed();
				end
			end
		elseif (hitGameObjectBelow:getCategory() == "Trampolin") then
			onTrampolin = true;
		end
	end
	
	-- Check what is in front of the player
	local hitGameObjectFront = playerController:getHitGameObjectFront();
	--log("hitGameObjectFront: ");
	if (hitGameObjectFront ~= nil) then
		walkCount = 0;
		if (inAir == true) then
			atObstacle = true;
		end

		--log("hitGameObjectFront: " .. hitGameObjectFront:getName());
		-- Halt when its a static collision object
		if (hitGameObjectFront:getPhysicsArtifactComponent() ~= nil) then
			playerController:setMoveWeight(0);
			playerController:getPhysicsComponent():setVelocity(playerController:getPhysicsComponent():getVelocity() * Vector3(0, 1, 0));
		end
	end
	
	-- Check what is above  the player
	local hitGameObjectAbove = playerController:getHitGameObjectUp();
	--log("hitGameObjectFront: ");
	if (hitGameObjectAbove ~= nil) then
		walkCount = 0;
		playerController:setMoveWeight(0);
		playerController:getPhysicsComponent():setVelocity(playerController:getPhysicsComponent():getVelocity() * Vector3(0, 1, 0));
		atObstacle = true;
	end
	 
	-----------------------------------------Handle idle--------------------------------------------------
	-- If no key is pressed or player is not able to move (moveWeight = 0), go to idle state
	if ((playerController:getMoveWeight() == 0) or (InputDeviceModule:isActionDown(NOWA_A_UP) == false and InputDeviceModule:isActionDown(NOWA_A_DOWN) == false
			and InputDeviceModule:isActionDown(NOWA_A_LEFT) == false and InputDeviceModule:isActionDown(NOWA_A_RIGHT) == false
			and jumpKeyPressed == false and isJumping == false)) then
	
		walkCount = 0;
		keyDirection = Vector3.ZERO;
		if (animationBlender:isAnimationActive(AnimationBlender.ANIM_IDLE_1) == false and inAir == false) then
			animationBlender:blend(AnimationBlender.ANIM_IDLE_1, AnimationBlender.BlendWhileAnimating, 0.2, true);
		end

		tempAnimationSpeed = playerController:getAnimationSpeed() * 0.5;
-- Attention: Due to rotation of 90 degree at once, commented this out
		--direction = NONE;
			
		-- No acceleration, move with usual constant speed
		if (playerController:getAcceleration() == 0) then
			acceleration = 1;
		else
			acceleration = acceleration - playerController:getAcceleration() * dt;
			if (acceleration <= 0.5) then
				acceleration = 0.5;
			end
		end

		boringTimer = boringTimer + dt;
		if (inAir == true) then
			boringTimer = 0;
		end
		
		-- If the user does nothing for 10 seconds, choose a random boring animation state
		if (boringTimer >= 10) then
			boringTimer = 0;
			local id = MathHelper:getRandomNumberInt(0, 3);
			local animID;
			if (0 == id) then
				animID = AnimationBlender.ANIM_IDLE_1;
			elseif (1 == id) then
				animID = AnimationBlender.ANIM_IDLE_2;
			else
				animID = AnimationBlender.ANIM_IDLE_3;
			end
			
			if (animationBlender:hasAnimation(animID) and animationBlender:isComplete()) then
				tempAnimationSpeed = playerController:getAnimationSpeed() * 0.5;
				animationBlender:blend(animID, AnimationBlender.BlendWhileAnimating, 0.2, true);
			end
		end
		
		if (playerController:isIdle() and playerController:getPhysicsComponent():getHasBuoyancy() == false) then
			playerController:getPhysicsComponent():setVelocity(playerController:getPhysicsComponent():getVelocity() * Vector3(0, 1, 0));
		end
	end
	
	-------------------------------------------Handle movement--------------------------------
	if (InputDeviceModule:isActionDown(NOWA_A_LEFT) or InputDeviceModule:isActionDown(NOWA_A_RIGHT) and atObstacle == false) then
			
		boringTimer = 0;

		-- walk if left or right is being pressed
		boringTimer = 0;

		local animId = AnimationBlender.ANIM_NONE;

		-- JumpNRun 2D treatement: Rotate til 90 degree at once
		if (InputDeviceModule:isActionDown(NOWA_A_LEFT)) then
			if (runAfterWalkTime > 0 and inAir == false) then
				walkCount = walkCount + dt;
			end
			-- Walked long enough without pause : run
			if (walkCount >= runAfterWalkTime) then
				animId = AnimationBlender.ANIM_RUN;
				tempSpeed = playerController:getPhysicsComponent():getMaxSpeed() * playerController:getMoveWeight();
				tempAnimationSpeed = tempAnimationSpeed * 0.5;
			else
				tempSpeed = playerController:getPhysicsComponent():getSpeed() * playerController:getMoveWeight();
				animId = AnimationBlender.ANIM_WALK_NORTH;
			end
			direction = LEFT;
			keyDirection = Vector3(-1, 0, 0);
		elseif (InputDeviceModule:isActionDown(NOWA_A_RIGHT)) then
			if (runAfterWalkTime > 0 and inAir == false) then
				walkCount = walkCount + dt;
			end
			-- Walked long enough without pause : run
			if (walkCount >= runAfterWalkTime) then
				animId = AnimationBlender.ANIM_RUN;
				tempSpeed = playerController:getPhysicsComponent():getMaxSpeed() * playerController:getMoveWeight();
				tempAnimationSpeed = tempAnimationSpeed * 0.5;
			else
				tempSpeed = playerController:getPhysicsComponent():getSpeed() * playerController:getMoveWeight();
				animId = AnimationBlender.ANIM_WALK_NORTH;
			end
			direction = RIGHT;
			keyDirection = Vector3(1, 0, 0);
		end
			
		directionMove = keyDirection * tempSpeed * acceleration;
		
		-- If player is stuck play corresponding animation
		--if (playerController:getMoveWeight() == 0) then
		--	animId = AnimationBlender.ANIM_HALT;
		--end
			
		if (animationBlender:isAnimationActive(animId) == false
			and (animationBlender:isComplete() or animationBlender:isAnimationActive(AnimationBlender.ANIM_IDLE_1)
				or animationBlender:isAnimationActive(AnimationBlender.ANIM_IDLE_2)
				or animationBlender:isAnimationActive(AnimationBlender.ANIM_IDLE_3))
				and playerController:getPhysicsComponent():getHasBuoyancy() == false
			and inAir == false and jumpKeyPressed == false and isJumping == false and playerController:getMoveWeight() == 1 and InputDeviceModule:isActionDown(NOWA_A_UP) == false) then
			
			tempAnimationSpeed = playerController:getAnimationSpeed();
			-- 0.02f: Immediately blend to walk
---------------------------------------------------------------------------------------------------
			animationBlender:blend(animId, AnimationBlender.BlendWhileAnimating, 0.2, true);
---------------------------------------------------------------------------------------------------
		end
			
	elseif (InputDeviceModule:isActionDown(NOWA_A_DUCK)) then
		boringTimer = 0;
		if (animationBlender:isAnimationActive(AnimationBlender.ANIM_DUCK) == false and duckedOnce == false) then
			duckedOnce = true;
			animationBlender:blend(AnimationBlender.ANIM_DUCK, AnimationBlender.BlendWhileAnimating, 0.1, false);
		end
		if (animationBlender:getTimePosition() >= animationBlender:getLength() - 0.3) then
			animationBlender:setTimePosition(0.7);
		end
	elseif (InputDeviceModule:isActionDown(NOWA_A_DUCK) == false and duckedOnce == true) then
		boringTimer = 0;
		duckedOnce = false;
	end
	
	---------------------------------Player Rotation---------------------------------------------------------------
	-- If the old direction does not match the current direction
	-- the player changed direction, but this only set the direction change to true, never to false, which is done, after a 90 degree turn has been accomplished
	if (oldDirection ~= direction) then
		directionChanged = true;
		walkCount = 0;
	end
		
	-- If the player changed direction, rotate the player from x to -x and vice version (+- 180 degree), after that directionChanged is set to false
	if (directionChanged == true) then
		boringTimer = 0;
		local yawAtSpeed = 0;
		local currentDegree = playerController:getPhysicsComponent():getOrientation():getYaw():valueDegrees();
		if (direction == RIGHT) then
			yawAtSpeed = playerController:getRotationSpeed();
			if (currentDegree >= 90) then
				directionChanged = false;
				yawAtSpeed = 0;
				playerController:getPhysicsComponent():setOrientation(Quaternion(Degree(90), Vector3.UNIT_Y));
			end
		elseif (direction == LEFT) then
			yawAtSpeed = -playerController:getRotationSpeed();
			if (currentDegree <= -90) then
				directionChanged = false;
				yawAtSpeed = 0;
				playerController:getPhysicsComponent():setOrientation(Quaternion(Degree(-90), Vector3.UNIT_Y));
			end
		end
		playerController:getPhysicsComponent():applyAngularImpulse(Vector3(0, yawAtSpeed, 0));
		
	else
		-- player should not rotate without intention
		if (direction == LEFT) then
			playerController:getPhysicsComponent():setOrientation(Quaternion(Degree(-90), Vector3.UNIT_Y));
		else
			playerController:getPhysicsComponent():setOrientation(Quaternion(Degree(90), Vector3.UNIT_Y));
		end
	end

	-- Prevent, that the player does bounce after falling
	if (inAir == false and playerController:getPhysicsComponent():getVelocity().y < -2 and onTrampolin == false and onSlider == false and isJumping == false) then
		playerController:getPhysicsComponent():setVelocity(directionMove);
	else
		playerController:getPhysicsComponent():setVelocity(playerController:getPhysicsComponent():getVelocity() * Vector3(0, 1, 0) + directionMove);
		if (inAir == false and direction ~= NONE) then
			-- walkSound:setSecondOffset(2);
			walkSound:setPitch(1);
			walkSound:setVolume(55);
			walkSound:setVelocity(playerController:getPhysicsComponent():getVelocity());
			-----------------------------walkSound:setActivated(true);
			-- walkSound:setRolloffFactor()
		end
	end
	
	---------------------------------Ragdoll Test------------------------------------------------------------------
	
	if timeSinceLastPush >= 0 then
		timeSinceLastPush = timeSinceLastPush - dt;
	end

	-- Test
	if timeSinceLastPush <= 0 then
		if (InputDeviceModule:isKeyDown(KeyEvent.KC_T) and canPush == true) then
			timeSinceLastPush = 1;
			-- Change to rag doll state, so that no rays etc. are calculated and player cannot move for 5 seconds
			playerController:getStateMachine():changeState(RagDollState);
			
			go = GameObjectController:getGameObjectFromId(989094932);
			go:getPhysicsRagDollComponent():setState("Ragdolling");
			
			canPush = false;
		end
	else
		canPush = true;
	end
	
	-----------------------------------------------Handle Jump---------------------------------------------------
	jumpKeyPressed = false;
	
	if (InputDeviceModule:isActionDown(NOWA_A_JUMP)) then
		boringTimer = 0;
		if (canDoubleJump == true) then
			
			if (jumpCount == 0) then
				jumpCount = jumpCount + 1;
				-- When a double jump is made, it must be made in air, else if the player presses the jump key immediately a second time, the player will jump to high
			elseif (relativeHeight > 3) then
				jumpCount = jumpCount + 1;
			end
			canDoubleJump = false;
			if (jumpCount > 2) then
				jumpCount = 0;
			end
		end
		if (tryJump == false) then
			jumpKeyPressed = true;
		end
	else
		-- In order that the player does not jump again and again if the jump key is hold, only set isJumping to false if the player released the jump key
		-- so that he can jump if jump key is pressed again
		tryJump = false;
		isJumping = false;
		canDoubleJump = true;
	end
	
	if (inAir == false and jumpKeyPressed == true and isJumping == false) then
		if (animationBlender:isAnimationActive(AnimationBlender.ANIM_JUMP_START) and animationBlender:isComplete()) then
			
		else
			animationBlender:blend(AnimationBlender.ANIM_JUMP_START, AnimationBlender.BlendSwitch, 0.2, false); -- do not know why, but this must stand here, else sometimes instead of jump, the walk anim is executed
			animationBlender:blend(AnimationBlender.ANIM_JUMP_START, AnimationBlender.BlendWhileAnimating, 0.2, false);
		end
		jumpSound:setActivated(true);
		boringTimer = 0;
		
	elseif (inAir == true and playerController:getPhysicsComponent():getVelocity().y < -2 and onSlider == false) then
		jumpCount = 0;
		if (animationBlender:isAnimationActive(AnimationBlender.ANIM_FALL) == false) then
			animationBlender:blend(AnimationBlender.ANIM_FALL, AnimationBlender.BlendWhileAnimating, 0.2, true);
		end
		jumpKeyPressed = false;
	end
	
	if (inAir == false and groundedOnce == false) then
		boringTimer = 0;
		-- Play only once!
		walkSound:setPitch(0.35);
		walkSound:setVolume(55);
		walkSound:setActivated(true);
		smokeParticle:setOffsetPosition(Vector3(0, -0.1, 1));
		smokeParticle:setActivated(true);
		groundedOnce = true;
	end
	
	if (inAir == true) then
		groundedOnce = false;
	end
	
	if (playerController:getJumpWeight() == 1 and (jumpKeyPressed == true and (isJumping == false and inAir == false) or (doubleJump == true and jumpCount == 2))) then
		boringTimer = 0;
		if (playerController:getPhysicsComponent():getVelocity().y <= jumpForce * jumpCount) then
			playerController:getPhysicsComponent():addImpulse(Vector3(0, jumpForce * playerController:getJumpWeight(), 0));
			if (jumpCount >= 2) then
				jumpCount = 0;
			end
		else
			isJumping = true;
			playerController:setJumpWeight(0);
		end
	end
	
	-- If the player is on ground and not jumping and the jump key pressed 
	if (jumpKeyPressed == true and (inAir == false and isJumping == false)) then
		tryJump = true;
	end

	animationBlender:addTime(dt * tempAnimationSpeed / animationBlender:getLength());
end

WalkState["exit"] = function(gameObject)

end

ragDollTime = 5;

RagDollState = { }

RagDollState["enter"] = function(gameObject)
	playerController = gameObject:getPlayerControllerJumpNRunLuaComponent();
	ragDollTime = 5;
	playerController:getPhysicsRagDollComponent():setState("Ragdolling");
end

RagDollState["execute"] = function(gameObject, dt)
	-- Let the ragdoll set the velocity last set from movement for 1 second
	if (ragDollTime >= 4) then
		playerController:getPhysicsComponent():setVelocity(playerController:getPhysicsComponent():getVelocity() * Vector3(0, 1, 0) + directionMove);
	end
	if (ragDollTime > 0) then
		ragDollTime = ragDollTime - dt;
	else
		playerController:getStateMachine():changeState(WalkState);
	end
end

RagDollState["exit"] = function(gameObject)
   playerController:getPhysicsRagDollComponent():setState("Inactive");
end
Best Regards
Lax
3 x

Post Reply