Infinite Jumper Game: Powerup issue

Hey guys so after about 3 weeks I decided to start making a simple infinite jumper game I have it fully working so far but I have a rocket boost that spawns every couple points. and the issue is whenever the user collects the powerup everything works as plan; disable gravity and set his Y velocity to max_booster_speed. Thing is the the player “transforms” into a rocket and flies upward for a few second before resetting but the player is twitching during that time I notice that if a set the max_booster_speed to something really low it doesnt happen. Im thinking its something to do with the physics update time and the gravity being ignored. Here is my entire player.script file if you guys could help me out.

local gravity = -20
local jump_takeoff_speed = 1100
--set gravity to zero when boosting
local max_booster_speed = 1300
local booster_points_giver
local booster_timer --10 seconds
local move_speed = 400
local current_height = 0
local allowupdate
local boosterAnimplayed
local player_dead
local currentAnimation
-- 0 player normal, 1 playerdead, 2 player boosted
local playerstate
local other_id = "null"

function init(self)
	  -- this tells the engine to send input to on_input() in this script
    msg.post(".", "acquire_input_focus")
    -- save the starting position
    self.position = go.get_position()
     msg.post("#", "reset")
     --set the height to send to camera for implementation
     current_height = go.get_position().y
    -- keep track of movement vector and if there is ground contact
    self.velocity = vmath.vector3(0, 0, 0)
    self.ground_contact = false
    playerstate = 0
    booster_points_giver = 0
    player_dead = false
    allowupdate = true
    currentAnimation = 0
    boosterAnimplayed = false
    booster_timer = 6
end

function final(self)
	-- Add finalization code here
	-- Remove this function if not needed
end


local function playanimationstate(self)
	if playerstate == 0 then
		if boosterAnimplayed then
		boosterAnimplayed = false
		end
		if self.velocity.y > 0 and currentAnimation == 1 then 
			msg.post("#playersprt","play_animation",{ id = hash("jump")})
			currentAnimation = 0
		elseif self.velocity.y < 0 and currentAnimation == 0 then
			msg.post("#playersprt","play_animation",{ id = hash("fall")})
			currentAnimation = 1
		end
	elseif playerstate == 2 and boosterAnimplayed == false then
		msg.post("#playersprt","play_animation",{ id = hash("booster")})
		boosterAnimplayed =true
		currentAnimation = 2
	end
	
end

function update(self, dt)
	if allowupdate then
		--set the gravity to a vec3 variable
		--increase current position if player is higher
			if(current_height < go.get_position().y) then
			current_height = go.get_position().y
			end
			self.position = go.get_position()
			--if there is no contact apply gravity and if the player is not in booster state
			if not self.ground_contact and playerstate ~= 2 then
			self.velocity.y = self.velocity.y + gravity
			end
		--clamp velocity
			--[[if self.velocity.y >= max_booster_speed then
			self.velocity.y = max_booster_speed
			end]]
			--sets the player position every frame based on velocity and deltaTime
			go.set_position(go.get_position() + self.velocity *dt)
			--create a 3vector correction at 0,0,0
			self.correction = vmath.vector3()
			--ground contact initailly false
			self.ground_contact = false
			--if player at the left most part of the view teleport him to the right side vice versa
			if self.position.x < -10 then
			self.position.x = 730
			go.set_position(vmath.vector3(self.position.x,self.position.y,0))
			elseif self.position.x > 730 then
			self.position.x = -10
			go.set_position(vmath.vector3(self.position.x,self.position.y,0))
			end
			--send a message to the camera giving the players position
			msg.post("game_camera","player_position",{position = go.get_position(), velocity = self.velocity})
			--msg.post("small_cloud","player_position",{position = go.get_position(), velocity = self.velocity})
			if playerstate == 2 then
				self.velocity.y = max_booster_speed
			booster_timer = booster_timer - 1 * dt
			booster_points_giver = booster_points_giver + 1 * dt
				if(booster_points_giver > 0.3) then
				msg.post("game_ui","add_score",{amount =  1}) 
				booster_points_giver = 0
				end
			end
			if booster_timer < 0 then
				particlefx.stop("#booster_flame")
				playerstate = 0
				currentAnimation = 0
				gravity = -20
				self.ground_contact = false
				booster_timer = 10
				booster_points_giver = 0
			end
			playanimationstate(self)
	end
end


local function handle_geometry_contact(self, normal, distance)
	-- project the correction vector onto the contact normal
	-- correction vector is the 0-vector for the first contact point
	local proj = vmath.dot(self.correction, normal)
	-- calculate the compensation we need to make for this contact point
	local comp = (distance - proj) * normal
	--apply the compensation to the player character
	go.set_position(go.get_position()+comp)
	--check if the normal points enough up to consider the player standing on the ground
	--(o.7 is roughly equal to 45 degree deviation from pure vertical direction)
	if normal.y > 0.7 then
		self.ground_contact = true
	end
	--project to velocity onto the normal 
	proj = vmath.dot(self.velocity, normal)
	--if the projection is negative, it means that some of the velocity points towards the contact point
	if proj < 0 then
		--remove that component in that case
		self.velocity = self.velocity - proj * normal
	end
		
end

local function jump(self)
	--only allow jump from platform
	if self.ground_contact then
		--set take-off speed
		particlefx.play("#pfx")
		self.velocity.y = jump_takeoff_speed
		self.ground_contact = false
	end
end



function on_message(self, message_id, message, sender)
	--check if player made contact with an object
	if message_id == hash("contact_point_response") then
		--if velocity less than 0 allow contact with platform and jump
		if self.velocity.y < 0 then
			if message.group == hash("platform")  then
				handle_geometry_contact(self, message.normal, message.distance)
				jump(self)
				--give player only one point per platform
				if other_id ~= message.other_id then
					msg.post("game_ui","add_score",{amount =  1})  
				    other_id = message.other_id
				end
         
			end
			--ground 
			if message.group == hash("ground")  then
				handle_geometry_contact(self, message.normal, message.distance)
				jump(self)       
			end
		end
		if message.group == hash("booster") then
			playerstate = 2
			particlefx.play("#booster_flame")
			self.velocity.y = max_booster_speed
			end
	end
	--check if player too far below camera position then call game over
	if message_id == hash("camera_position") then
		if go.get_position().y < message.position.y - message.offset then
			player_dead = true;
			msg.post("game_camera","player_dead")
			msg.post("game_ui", "player_dead")
			
		end
	end
	if message_id == hash("game_paused") then
		allowupdate = false
	elseif message_id == hash("game_resumed") then
		allowupdate= true
	end
	
end

function on_input(self, action_id, action)
	if allowupdate then
	if action_id == hash("MOVE_LEFT") and action.pressed then
		self.velocity.x = -move_speed
		go.set_rotation(vmath.quat_axis_angle(vmath.vector3(0,0,1),-50))
	elseif action_id == hash("MOVE_RIGHT") and action.pressed then
		self.velocity.x = move_speed
		go.set_rotation(vmath.quat_axis_angle(vmath.vector3(0,0,1),50))
	end
	
	if action_id == hash("MOVE_LEFT") and action.released or action_id == hash("MOVE_RIGHT") and action.released then
	self.velocity.x = 0;	
		go.set_rotation(vmath.quat_axis_angle(vmath.vector3(0,0,1),0))
	end
	--mobile/pc
	
	if action_id==hash("LEFT_CLICK") and action.pressed then 
		--left side of screen
		if action.x < 360 then
			self.velocity.x = -move_speed
			go.set_rotation(vmath.quat_axis_angle(vmath.vector3(0,0,1),-50))
		elseif action.x > 360 then
			--right side
			self.velocity.x = move_speed
			go.set_rotation(vmath.quat_axis_angle(vmath.vector3(0,0,1),50))
		end
	elseif action_id==hash("LEFT_CLICK") and action.released then
		self.velocity.x = 0;	
		go.set_rotation(vmath.quat_axis_angle(vmath.vector3(0,0,1),0))
	end
	end
end

function on_reload(self)
	-- Add reload-handling code here
	-- Remove this function if not needed
end

Here is a short video of the issue watch up until I collect the rocket powerup: https://youtu.be/cgFIkD4TJdM

It was a little bit hard to see from the video, but it’s only the player that is choppy right and not the platforms? What kind of vertical position does the player have? Could it be a shader precision issue, as discussed here, here and here.

Thanks for the reply. the players Y position always increases. The platforms are in one place(i.e their spawn location) and are removed once the player is far enough above them and vice versa they are spawned above him off screen. There is never more that 6 platforms spawned at a time. I noticed when gravity is re-enabled the twitching stops and everything goes back to normal until the next booster pickup.

Just an update. So I set a booter powerup to spawn at the beginning of the level and the same thing happens. Doesn’t seem to be anything to do with high Y values even though I know that could most likely become another issue. Ill review my code to see if I did something wrong.

1 Like