Double Jump

Hi guys and thanks very much for the read. I’m curious of simple functions that would allow my main character to do addition jumps upon press space more than once? 

This is the way I’ve been single jumping.

 function instance:jump() if not self.jumping then self:applyLinearImpulse( 0, -880 ) instance:setSequence( "jump" ) self.jumping = true end

At the moment i have Space bar for jump. 

If that is easy enough to answer i would also be curious about jumping off walls as well. 

Thank you so much for any help you can provide. 

self.jumping = 0 function instance:jump() if self.jumping\<2 then self:applyLinearImpulse( 0, -880 ) instance:setSequence( "jump" ) self.jumping = self.jumping+1 end

Is it what you are looking for?

That looks right to me! However upon trying that i keep getting an error. "attempt to index global ‘self’ (a nil trace back) 

I did try and play with it for a bit but i couldn’t get it to work. Should the line start with self.jumping = 0 ? 

I really appreciate your help Remi, any other suggestions? Thanks so much!

Try:  instance.jumping instead of self.jumping outside of the :jump() function.  You get a variable “self” inside the function because the colon operator will pass the value of instance to the function as “self”. But outside of that : based function, you have to reference the object by name.

Rob

Thanks very much for that Rob. I think i understand what you meant I tried this 

function M.new( instance, options ) ---tons of stuff missing here obviously for posting sake! instance.jumping = 0 function instance:jump() if self.jumping\<2 then self:applyLinearImpulse( 0, -880 ) instance:setSequence( "jump" ) self.jumping = self.jumping+1 end end

My game did launch but the second i hit my jump button i got an error “attempt to compare boolean with number stack trace back”, did i misunderstand? Thanks in advance! 

Is the error happening on the line of code: if.self.jumping < 2 then ??? or somewhere else?

Thanks

Rob

That is correct Rob! Thanks! 

  dyCTYun.png

 if self.jumping\<2 then

Well, the 2 is clearly a number, so for some reason Corona believes that self.jumping is a boolean (true/false).  Perhaps you have another line of code setting .jumping to true or false that’s not in the snippet you shared. You can verify this by doing a::

print( type( self.jumping ) )

But we don’t have enough information to say why it’s being set to a boolean.

Rob

Thanks for that Rob. I am stumped on this one. That is the sole Jumping function i have.I searched my entire hero.Lua (confirmed with a search) and i don’t even have a Boolean in the entire code? Also i attempted a print and i received boolean in the feed but i have no clue where it would be set as such. I am still playing around with the sticker knight template learning. Here is the code for the hero.lua.

local fx = require( "com.ponywolf.ponyfx" ) local composer = require( "composer" ) -- Define module local M = {} function M.new( instance, options ) -- Get the current scene local scene = composer.getScene( composer.getSceneName( "current" ) ) local sounds = scene.sounds -- Default options for instance options = options or {} -- Store map placement and hide placeholder instance.isVisible = false local parent = instance.parent local x, y = instance.x, instance.y -- Load spritesheet local sheetData = { width = 192, height = 256, numFrames = 79, sheetContentWidth = 1920, sheetContentHeight = 2048 } local sheet = graphics.newImageSheet( "scene/game/img/sprites.png", sheetData ) local sequenceData = { { name = "idle", frames = { 1 } }, { name = "walk", frames = { 2, 3, 4, 5 }, time = 333, loopCount = 0 }, { name = "jump", frames = { 6 } }, { name = "ouch", frames = { 7 } }, } instance = display.newSprite( parent, sheet, sequenceData ) instance.x,instance.y = x, y instance:setSequence( "idle" ) -- Add physics physics.addBody( instance, "dynamic", { radius = 54, density = 3, bounce = 0, friction = 1.0 } ) instance.isFixedRotation = true instance.anchorY = 0.77 -- Keyboard control local max, acceleration, left, right, flip = 500, 5000, 0, 0, 0 local lastEvent = {} local function key( event ) local phase = event.phase local name = event.keyName if ( phase == lastEvent.phase ) and ( name == lastEvent.keyName ) then return false end -- Filter repeating keys if phase == "down" then if "left" == name or "a" == name then left = -acceleration flip = -0.133 end if "right" == name or "d" == name then right = acceleration flip = 0.133 elseif "space" == name or "buttonA" == name or "button1" == name then instance:jump() print( type( self.jumping ) ) end if not ( left == 0 and right == 0 ) and not instance.jumping then instance:setSequence( "walk" ) instance:play() end elseif phase == "up" then if "left" == name or "a" == name then left = 0 end if "right" == name or "d" == name then right = 0 end if left == 0 and right == 0 and not instance.jumping then instance:setSequence("idle") end end lastEvent = event end instance.jumping = 0 function instance:jump() if self.jumping\<2 then self:applyLinearImpulse( 0, -880 ) instance:setSequence( "jump" ) self.jumping = self.jumping+1 end end function instance:hurt() fx.flash( self ) audio.play( sounds.hurt[math.random(2)] ) if self.shield:damage() \<= 0 then -- We died fx.fadeOut( function() composer.gotoScene( "scene.refresh", { params = { map = self.filename } } ) end, 1500, 1000 ) instance.isDead = true instance.isSensor = true self:applyLinearImpulse( 0, -500 ) -- Death animation instance:setSequence( "ouch" ) self.xScale = 1 transition.to( self, { xScale = -1, time = 750, transition = easing.continuousLoop, iterations = -1 } ) -- Remove all listeners self:finalize() end end function instance:collision( event ) local phase = event.phase local other = event.other local y1, y2 = self.y + 50, other.y - ( other.type == "enemy" and 25 or other.height/2 ) local vx, vy = self:getLinearVelocity() if phase == "began" then if not self.isDead and ( other.type == "blob" or other.type == "enemy" ) then if y1 \< y2 then -- Hopped on top of an enemy other:die() elseif not other.isDead then -- They attacked us self:hurt() end elseif self.jumping and vy \> 0 and not self.isDead then -- Landed after jumping self.jumping = false if not ( left == 0 and right == 0 ) and not instance.jumping then instance:setSequence( "walk" ) instance:play() else self:setSequence( "idle" ) end end end end function instance:preCollision( event ) local other = event.other local y1, y2 = self.y + 50, other.y - other.height/2 if event.contact and ( y1 \> y2 ) then -- Don't bump into one way platforms if other.floating then event.contact.isEnabled = false else event.contact.friction = 0.1 end end end local function enterFrame() -- Do this every frame local vx, vy = instance:getLinearVelocity() local dx = left + right if instance.jumping then dx = dx / 4 end if ( dx \< 0 and vx \> -max ) or ( dx \> 0 and vx \< max ) then instance:applyForce( dx or 0, 0, instance.x, instance.y ) end -- Turn around instance.xScale = math.min( 1, math.max( instance.xScale + flip, -1 ) ) end function instance:finalize() -- On remove, cleanup instance, or call directly for non-visual instance:removeEventListener( "preCollision" ) instance:removeEventListener( "collision" ) Runtime:removeEventListener( "enterFrame", enterFrame ) Runtime:removeEventListener( "key", key ) end -- Add a finalize listener (for display objects only, comment out for non-visual) instance:addEventListener( "finalize" ) -- Add our enterFrame listener Runtime:addEventListener( "enterFrame", enterFrame ) -- Add our key/joystick listeners Runtime:addEventListener( "key", key ) -- Add our collision listeners instance:addEventListener( "preCollision" ) instance:addEventListener( "collision" ) -- Return instance instance.name = "hero" instance.type = "hero" return instance end return M&nbsp;

I am still learning and playing with corona templates until I am comfortable to start my own. Thanks again for the help. :slight_smile:

Maybe share more code?

Rob

I am sorry for sharing so much. I just wanted to be sure i wasn’t going crazy and over looking something. Sorry about that Rob.

In your collision function you have this line:

self.jumping = false

this will cause jumping to become boolean instead of a number. You also have several places in your code where you’re testing self.jumping to be true or false instead of testing against a number.

I didn’t take time to fully read your code to understand the impact of making .jumping into a number everywhere. If you need to know if the character is jumping and also know the jump count, I would use two better named variables:

instance.isJumping = boolean

instance.jumpCount = number of jumps

Rob

Thanks for that Rob. I will spend more time on this one! I truly appreciate your time, I have a lot to learn. 

self.jumping = 0 function instance:jump() if self.jumping\<2 then self:applyLinearImpulse( 0, -880 ) instance:setSequence( "jump" ) self.jumping = self.jumping+1 end

Is it what you are looking for?

That looks right to me! However upon trying that i keep getting an error. "attempt to index global ‘self’ (a nil trace back) 

I did try and play with it for a bit but i couldn’t get it to work. Should the line start with self.jumping = 0 ? 

I really appreciate your help Remi, any other suggestions? Thanks so much!

Try:  instance.jumping instead of self.jumping outside of the :jump() function.  You get a variable “self” inside the function because the colon operator will pass the value of instance to the function as “self”. But outside of that : based function, you have to reference the object by name.

Rob

Thanks very much for that Rob. I think i understand what you meant I tried this 

function M.new( instance, options ) ---tons of stuff missing here obviously for posting sake! instance.jumping = 0 function instance:jump() if self.jumping\<2 then self:applyLinearImpulse( 0, -880 ) instance:setSequence( "jump" ) self.jumping = self.jumping+1 end end

My game did launch but the second i hit my jump button i got an error “attempt to compare boolean with number stack trace back”, did i misunderstand? Thanks in advance! 

Is the error happening on the line of code: if.self.jumping < 2 then ??? or somewhere else?

Thanks

Rob

That is correct Rob! Thanks! 

  dyCTYun.png

 if self.jumping\<2 then

Well, the 2 is clearly a number, so for some reason Corona believes that self.jumping is a boolean (true/false).  Perhaps you have another line of code setting .jumping to true or false that’s not in the snippet you shared. You can verify this by doing a::

print( type( self.jumping ) )

But we don’t have enough information to say why it’s being set to a boolean.

Rob