Jump to content

Mouse Angle & Mouse Cross Hair


WazMeister
 Share

Recommended Posts

Hi All,

 

I'm still trying and still failing to get a nice Top Down Shooter PlayerCharacter with mouse aiming.  So I've managed to get Top Down view, some nice animations and movements with help of @Alienhead.  My current situation is mouse pointer is locked to center of screen and clamped,  I've messed around with code for countless hours and can not seem to get the mouse unlocked without the angle of player spinning at 10000mph!

What I would like to understand and achieve, is having mouse unlocked so it moves freely around the screen (possibly clamping it again at a later date but not so restrictive to center of screen), maintain character direction facing where mouse is and finally having mouse cursor be a cross hair.

 

Please can someone help me, racking my brains and ripping out (the little I have left) of my hair, I've also hit my head with my fresh new Lua Programming by Roberto Ierusalimschy book!.  I just need bit of guidance in a real beginner / understandable way.  Thanks in advanced for any assistance you can provide.

A video of what I'm currently left with... to help 

 

local runmultiplier = 0.8

--Set Script properties in Editor / define variables
Script.lookSpeed = 0.2--float "Look Speed"
Script.lookSmoothing = 5--float "Look Smoothing"
Script.cameraDistance = 6--float "Camera Distance"
Script.cameraRadius = 0
Script.jumpStrength = 8--float "Jump Strength"
Script.walkSpeed = 2.5--float "Walk Speed"
Script.runSpeed = 5--float "Run Speed"
Script.cameraPitch = 35--float "Camera Pitch"
Script.lockCameraAngle = false--bool "Lock Camera"
Script.cameraCollision = true--bool "Camera Collision"

--====================================================================================================
function Script:Start()

	--Set the type to player,  keyvalue is string value associated with a key name
	self.entity:SetKeyValue("type", "player")
	
	--Create variable for player Mass
	self.mass = 10
	
	--check and set the mass of player for physics.
	if self.entity:GetMass() == 0 then
		self.entity:SetMass(10)
	end

	--Set player physics mode -  as a Character Controller Physics.
	self.entity:SetPhysicsMode(Entity.CharacterPhysics)
	
	-- Create a Camera to see the game!
	self.camera = Camera:Create()
	--Listener for spatial sound (location of sound)
	self.listener = Listener:Create(self.entity)
	--Get the player angle (rotation) of y axis and store in variable angle
	self.angle = self.entity:GetRotation().y
	--Set camereaAngle varible to players current y axis/angle + character controller angle.
	self.cameraAngle = self.angle + self.entity:GetCharacterControllerAngle()
	--Set Field Of View (FOV) for camera. Default is 90 
	self.camera:SetFOV(80)
	camera = self.camera

	--Create Table named 'player' and set it's fields / data
	player = {}
	player.ent = self.entity
	player.state = 1
	player.animationMode = ""
	player.holdAngle = self.angle
	player.timer_afk = Time:Millisecs() + 30000
	player.timer_jump = 0
	player.afk = true
	player.doublejump = 0
	player.stamina = 100
	player.staminaTotal = 100
	player.health = 100
	player.healthTotal = 100

	self.timer_rolled = 0
	self.timer_duringRoll = 0
	self.timer_rollLeft = 0
	self.timer_rollRight = 0
	self.timer_rollForward = 0
	self.timer_rollBackward = 0
	self.tick_firingRock = 0
	self.timer_tick = 0
	self.hKeyHit_firing = false
	self.timer_playerFired = 0
	self.releasePower = 0
	self.sndBreathPlaying = false

	--Player states (Setup in a lua table with fields)
	state = {} --Table called state
	--Add fields to table
	state.idle = 0
	state.walk = 1
	state.run = 2
	state.carry = 3
	state.dead = 4

-- Timer Variable for animations (see States further below)
	player.timer_dontChangeAnim = 0

-- Create pivot point for player
	player.infrontMarker = Pivot:Create()

end
	
--====================================================================================================
function Script:UpdateWorld()
	local playerPos = self.entity:GetPosition(true)
	local aabb = self.entity:GetAABB(Entity.GlobalAABB)
	playerPos.y = aabb.center.y
	self.camera:SetPosition(playerPos)
	context:DrawText("AABB: "..aabb:ToString(), 20, 20)
	context:DrawText("Camrea Pitch: "..self.cameraPitch, 40, 40)

	--Returns a value interpolated between a current and target angle for smooth movement. <Target (being moved towards in degrees, current value in degrees, the number to divide the diffrence by>
	self.cameraAngle = Math:CurveAngle(self.angle + self.entity:GetCharacterControllerAngle(), self.cameraAngle, self.lookSmoothing / Time:GetSpeed())
	
	--Set Camera intitial position (rotation and turn)
	if self.lockCameraAngle == false then
		self.camera:SetRotation(0, self.cameraAngle+180, 0)
		self.camera:Turn(90, 0, 0)
	else
		--If camera locked, set it to just camerapitch.
		self.camera:SetRotation(self.cameraPitch, 0, 0)
	end
	--Transform geomtry from one space to another. (x, y, z, entity source, entity destination)
	local cameraPos = Transform:Point(0, 0, -self.cameraDistance, self.camera, nil)
	
	--Set pick mode for camera collide
	local pickMode = self.entity:GetPickMode()
	self.entity:SetPickMode(0)

	if self.camereaCollision then
		local pickInfo = PickInfo()
		--[[A world pick, perform pick on all entities in a world that intersect,
		the specified line. Pick(origin of ray, end of ray, pick info container,
		radius, closet, col type)]]--
		if self.entity.world:Pick(playerPos, CameraPos, pickInfo, self.cameraRadius) then
			self.camera:SetPosition(pickInfo.position, true)
		else
			self.camera:SetPosition(cameraPos, true)
		end
	else
		self.camera:SetPosition(cameraPos, true)
	end
	self.camera:Move(0, 2, 0) -- Height adjust
	
	self.entity:SetPickMode(pickMode)
end

--====================================================================================================
function Script:UpdatePhysics()
	--use current window and context render surface
	local window = Window:GetCurrent()
	local context = Context:GetCurrent()

-- Setup / start
	local time = Time:Millisecs() --Time class for keeping track of application time. Millisecs returns system time in milliseconds
	local animationState = ""

--Move the player pivot (front marker) to current entity (player) position in local space (not global)
	player.infrontMarker:SetPosition(self.entity:GetPosition(true)) --Set position of pivot to player each frame/update
	local rot = self.camera:GetRotation(true)
	player.infrontMarker:SetRotation(0, rot.y, 0) -- set pivot angle/rotation to cameras current y angle (yaw).
	player.infrontMarker:Move(0, 0, 2) -- Move pivot on Z axis

-- Define variables
	--Get the enter position of screen / surface (context) and hold it in varibles cx and cy
	local cx = context:GetWidth()/2
	local cy = context:GetHeight()/2
		
-- Camera Angle
	--If camera is not locked then set mouse to center and clamp it
	if self.lockCameraAngle == false then
		local mousePos = window:GetMousePosition()
		window:SetMousePosition(cx, cy)

		local mx = Math:Clamp(mousePos.x - cx, -90, 90)
		local my = Math:Clamp(mousePos.y - cy, -45, 45) - .5
		
		--Setup rotate (angle) to mouse movement for player.
		if self.smoothedMouseMovement ~= nil then
			self.angle = self.angle + mx * self.lookSpeed --angle of entity + mouse X & a speed. enty faces mouse movement on X
		else
			self.smoothedMouseMovement = Vec2(0)
		end
		--Returns a value interpolated between a current and target value. <Target (the value being moved towards, current (the current value), division (number to divide diffrent by)
		self.smoothedMouseMovement.x = Math:Curve(mx, self.smoothedMouseMovement.x, self.lookSmoothing)
		self.smoothedMouseMovement.y = Math:Curve(my, self.smoothedMouseMovement.y, self.lookSmoothing)
						
		--up and down adjust of mouse movement (turning X) and limit it
		if self.cameraPitch < -5 then self.cameraPitch = -5 end
		if self.cameraPitch > 65 then self.cameraPitch = 65 end
		--[[Apply mouse movement (up & down) via smooth movement.y,
		based on cameraPitch set to camrea turn]]
		self.cameraPitch = self.cameraPitch + (self.smoothedMouseMovement.y) * .1
		--player.cameraPitch = self.cameraPitch
		--self.entity:SetInput(self.angle, 0, 0, 0)				
	end
	window:ShowMouse()


	--Set key button varibles
	local move = 0
	local strafe = 0
	local keyHit_forward = false
	local keyHit_backward = false
	local keyHit_left = false
	local keyHit_right = false

	--Player Movement Variables
	keyHit_forward = window:KeyDown(Key.W)
	keyHit_backward = window:KeyDown(Key.S)
	keyHit_left = window:KeyDown(Key.A)
	keyHit_right = window:KeyDown(Key.D)
	
	--Reset player to IDLE STATE
	if move == 0 or strafe == 0 then
		player.state = 1
	end

	--Key Actions
	--::rescanactions::
	if keyHit_forward and keyHit_backward then
		player.state = 1
	else
		if keyHit_forward then
			move = -self.walkSpeed
			player.state = 2
		elseif keyHit_backward then
			move = self.walkSpeed
			player.state = 3
		end
	end

	if keyHit_right and keyHit_left then
		player.state = 1
	else
		if keyHit_left then
			strafe = self.walkSpeed
			player.state = 4
	elseif keyHit_right then
			strafe = -self.walkSpeed
			player.state = 5
		end
	end

	--=============================================================================================================
	--Player States
	--=============================================================================================================

	--IDLE STATE (1)
	if player.state == 1 then
		if player.timer_dontChangeAnim < time then --time_dontChangeAnim is intitalise to 0 so will always be less than time...?
			--Determine which idle animation to play
			--if player.stamina < 60 then
				--animationState = "Exhausted"
			--else
				animationState = "Idle"
			--end
		
			if player.animationState ~= animationState then --If the player.animationState does not hold or match a animation, then set the player.animationState field to current animation (held in variable)
				player.animationState = animationState
				player.ent:PlayAnimation(player.animationState, .03, 250, 0)--Play the animation.  player.ent table/field  basically replaces  self.entity.
			end
		end
		
		self.entity:SetInput(player.holdAngle, 0, 0, 0)
	end
---------------------------------------------------------------------
	--WALK STATE (2)
	if	player.state == 2 then
		if player.timer_dontChangeAnim < time then
			animationState = "Walk"
			if player.animationState ~= animationState then
				player.animationState = animationState
				player.ent:PlayAnimation(player.animationState, .06, 250, 0)
				--add sound
			end
		end

		self.entity:SetInput(self.angle, move, strafe, 0)
		player.holdAngle = self.angle	
	end
---------------------------------------------------------------------
--WALKBACKWARDS STATE (3)
	if player.state == 3 then
		if player.timer_dontChangeAnim < time then
			animationState = "Walkbackwards"
			if player.animationState ~= animationState then
				player.animationState = animationState
				player.ent:PlayAnimation(player.animationState, .05, 250, 0)
			end
		end

		self.entity:SetInput(self.angle, move, strafe, 0)
		player.holdAngle = self.angle
	end
---------------------------------------------------------------------
--STRAFE LEFT STATE (4)
	if player.state == 4 then
		if player.timer_dontChangeAnim < time then
			animationState = "StrafeLeft"
			if player.animationState ~= animationState then
				player.animationState = animationState
				player.ent:PlayAnimation(player.animationState, .04, 250, 0)
				--add sound
			end
		end

		self.entity:SetInput(self.angle, move, strafe, 0)
		player.holdAngle = self.angle
	end
---------------------------------------------------------------------
--STRAFE RIGHT STATE (5)
	if player.state == 5 then
		if player.timer_dontChangeAnim < time then
			animationState = "StrafeRight"
			if player.animationState ~= animationState then
				player.animationState = animationState
				player.ent:PlayAnimation(player.animationState, .04, 250, 0)
				--add sound
			end
		end

		self.entity:SetInput(self.angle, move, strafe, 0)
		player.holdAngle = self.angle
	end
---------------------------------------------------------------------
--STRAFE RIGHT STATE (5)
	if player.state == 6 then
		if player.timer_dontChangeAnim < time then
			animationState = "StrafeRight"
			if player.animationState ~= animationState then
				player.animationState = animationState
				player.ent:PlayAnimation(player.animationState, .04, 150, 0)
				--add sound
			end
		end

		self.entity:SetInput(self.angle, move, strafe, 0)
		player.holdAngle = self.angle
	end
---------------------------------------------------------------------



end

 

Dream since child of making games! From Game Programming Starter Kit 3.0, Blitz Basic, Map Creation since Duke 3D, Game Maker, Blitz3D (of recent..2023) and many other engines and years..... never really sticking to it with inner struggles that I've had to fight along with pushing to learn and acheive.

40 years old.. came across Leadwerks on Steam... Learning slowly but surely and loving it!

Learn with me or just watch me fail! at my random Youtube Channel, as I stream adhoc while learning and using LeadWerks and other game creating tools.

https://www.youtube.com/@wazmeister3151/featured

Link to comment
Share on other sites

I'm not 100% sure what your trying to do there.. Traditionally there is no looked-mouse support for town down game. Are you trying to install point and click-walk ability?  That would be pretty easy to without a controller just using LE's homebrew pathfinding class..  which by the way works pretty damn awesomally I might add.

Link to comment
Share on other sites

Hi Alien,

 

I would like to get similair player control as these examples. 

 

 

 

Dream since child of making games! From Game Programming Starter Kit 3.0, Blitz Basic, Map Creation since Duke 3D, Game Maker, Blitz3D (of recent..2023) and many other engines and years..... never really sticking to it with inner struggles that I've had to fight along with pushing to learn and acheive.

40 years old.. came across Leadwerks on Steam... Learning slowly but surely and loving it!

Learn with me or just watch me fail! at my random Youtube Channel, as I stream adhoc while learning and using LeadWerks and other game creating tools.

https://www.youtube.com/@wazmeister3151/featured

Link to comment
Share on other sites

Did them videos make it any clearer?

 

Anyone able to assist me in the right direction? Just need a little helping hand to guide me through this dark tunnel.

 

Dream since child of making games! From Game Programming Starter Kit 3.0, Blitz Basic, Map Creation since Duke 3D, Game Maker, Blitz3D (of recent..2023) and many other engines and years..... never really sticking to it with inner struggles that I've had to fight along with pushing to learn and acheive.

40 years old.. came across Leadwerks on Steam... Learning slowly but surely and loving it!

Learn with me or just watch me fail! at my random Youtube Channel, as I stream adhoc while learning and using LeadWerks and other game creating tools.

https://www.youtube.com/@wazmeister3151/featured

Link to comment
Share on other sites

I haven't made a game like this but this is how I would go about it.

Split your main character into 2 parts.

Part 1 is the legs which will be controlled by the WASD keys. the animation for them determined by which way the player wants to go.

Keep the "legs" in the center of the screen and move the map in the opposite direction to which the player wants to move.

Part 2 will be the torso, weapon and head of the character. Parent this part to the legs. Animation of this part is determined by the position of the mouse pointer.

With the mouse pointer you will need to hide the default pointer and replace it with a suitable crosshair. 

In this post Macklebee describes the process.

  You will need to constrain the "mouse" so that it does not leave the screen.

Hope this helps and good luck.

  • Like 1
Link to comment
Share on other sites

Thanks, that really insightful and helpful.

 

Not sure the proposal is the solution I need.  It must be something Leadwerks can acheive,  its basically top down view,  rotation/math curve for model towards mouse location and then mouse icon being a cross hair that use used to aim and shoot etc....

Just not sure how to piece it all together in Lua.

 

Dream since child of making games! From Game Programming Starter Kit 3.0, Blitz Basic, Map Creation since Duke 3D, Game Maker, Blitz3D (of recent..2023) and many other engines and years..... never really sticking to it with inner struggles that I've had to fight along with pushing to learn and acheive.

40 years old.. came across Leadwerks on Steam... Learning slowly but surely and loving it!

Learn with me or just watch me fail! at my random Youtube Channel, as I stream adhoc while learning and using LeadWerks and other game creating tools.

https://www.youtube.com/@wazmeister3151/featured

Link to comment
Share on other sites

You'll need an unlocked mouse pointer..   preform a simple Pick to get the location the mouse is at and rotate the player to that position.  leadwerks is a full blown game engine, it can do most likely anything you wish for it to do but you'll need to know the commands and their outcome in order to select the appropriate method.

https://www.leadwerks.com/learn?page=API-Reference_Object_Entity_Camera_Pick

pickinfo.position will contain the location you want, you could then place a pivot or whatever there then Point() the player towards it ( on Y axis only ) .

Link to comment
Share on other sites

Okay  I went ahead and did that part of my code.  Is this kinda what your looking to do ?

	-- do a pick
	local pickinfo = PickInfo()
	local pickradius = .1
	local p = window:GetMousePosition()
	if (cam:Pick(p.x,p.y,pickinfo,pickradius,true)) then
		   enginepiv:SetPosition(pickinfo.position)
		   self.player:Point(enginepiv)
		   self.player:SetRotation(0, self.player:GetRotation().y-180, 0)
	end

if your using a physics controller on your player you'll need to set the self.angle to Y rotation ( SetInput() ) and not use the Point() method as shown above. I have no physics on the ant so I used the Point() method but in theory it's the same practice.

 

  • Like 1
  • Thanks 1
  • Upvote 1
Link to comment
Share on other sites

5 hours ago, Alienhead said:

Okay  I went ahead and did that part of my code.  Is this kinda what your looking to do ?

	-- do a pick
	local pickinfo = PickInfo()
	local pickradius = .1
	local p = window:GetMousePosition()
	if (cam:Pick(p.x,p.y,pickinfo,pickradius,true)) then
		   enginepiv:SetPosition(pickinfo.position)
		   self.player:Point(enginepiv)
		   self.player:SetRotation(0, self.player:GetRotation().y-180, 0)
	end

if your using a physics controller on your player you'll need to set the self.angle to Y rotation ( SetInput() ) and not use the Point() method as shown above. I have no physics on the ant so I used the Point() method but in theory it's the same practice.

I'll have to finish work to look at this in detaill.. but wow! That is amazing, not just the response but the time and effort shown to help me.  Really geninue and touching,  you're amazing Ronnie - Reminds me all humans are not bad! ;)

It's not exactly what I am after, I want as you shown, but player does not follow where mouse is, just the angle and when shooting with mouse it shoots at location (hence the mouse cursor I will eventually turn to a 2D crosshair as if its looking down from above as well..  Top Down Shooter).

I should be able to review the above and amend it so the W,A,S,D keys move player around and not follow the mouse pointer.. but mouse hopefully to be free as you've shown and player angle look at it.

 

  • Like 1

Dream since child of making games! From Game Programming Starter Kit 3.0, Blitz Basic, Map Creation since Duke 3D, Game Maker, Blitz3D (of recent..2023) and many other engines and years..... never really sticking to it with inner struggles that I've had to fight along with pushing to learn and acheive.

40 years old.. came across Leadwerks on Steam... Learning slowly but surely and loving it!

Learn with me or just watch me fail! at my random Youtube Channel, as I stream adhoc while learning and using LeadWerks and other game creating tools.

https://www.youtube.com/@wazmeister3151/featured

Link to comment
Share on other sites

10 hours ago, Alienhead said:

Okay  I went ahead and did that part of my code.  Is this kinda what your looking to do ?

	-- do a pick
	local pickinfo = PickInfo()
	local pickradius = .1
	local p = window:GetMousePosition()
	if (cam:Pick(p.x,p.y,pickinfo,pickradius,true)) then
		   enginepiv:SetPosition(pickinfo.position)
		   self.player:Point(enginepiv)
		   self.player:SetRotation(0, self.player:GetRotation().y-180, 0)
	end

if your using a physics controller on your player you'll need to set the self.angle to Y rotation ( SetInput() ) and not use the Point() method as shown above. I have no physics on the ant so I used the Point() method but in theory it's the same practice.

Sorry Ron, I've had a look but even more confused.

Not sure what Point() you reference to in my code?

 

Am I to use/edit the code you detailed or just set self.angle of player to my camera rotation in setinput?

Many Thanks again

 

Dream since child of making games! From Game Programming Starter Kit 3.0, Blitz Basic, Map Creation since Duke 3D, Game Maker, Blitz3D (of recent..2023) and many other engines and years..... never really sticking to it with inner struggles that I've had to fight along with pushing to learn and acheive.

40 years old.. came across Leadwerks on Steam... Learning slowly but surely and loving it!

Learn with me or just watch me fail! at my random Youtube Channel, as I stream adhoc while learning and using LeadWerks and other game creating tools.

https://www.youtube.com/@wazmeister3151/featured

Link to comment
Share on other sites

100% agree, but also noticed you reminisce a lot.

Dream since child of making games! From Game Programming Starter Kit 3.0, Blitz Basic, Map Creation since Duke 3D, Game Maker, Blitz3D (of recent..2023) and many other engines and years..... never really sticking to it with inner struggles that I've had to fight along with pushing to learn and acheive.

40 years old.. came across Leadwerks on Steam... Learning slowly but surely and loving it!

Learn with me or just watch me fail! at my random Youtube Channel, as I stream adhoc while learning and using LeadWerks and other game creating tools.

https://www.youtube.com/@wazmeister3151/featured

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...