How do I move this turret using a slider?

Hello!
 
As you can see by the title, I am trying to control my turret using a slider.  I created this game from a cannonball tutorial that used buttons to control movement.  
 
I have created a working slider that moves up and down within a certain area, but I don’t know how to make it control the turret.

Code:

[spoiler]

--Oliver Duce --Shooty game --2015 local background = display.newImage("bg2.png",0,0) --Define the variables rotateAmt = 5 rotateMin = -90 rotateMax = 40 turretRotation = 0 turretForce = 1200 playerPoints = 0 targetHit = false timeLeft = 500 --Define the functions function closeDownApp(event) --os.exit() end function update( ) --decrease the time counter timeLeft = timeLeft - 1 scoreDisplay.text = 'Score: ' .. playerPoints .. ' Time: ' .. timeLeft --check if the time has run out if (timeLeft \<= 0) then --display the final score scoreDisplay.text = 'Final Score: ' .. playerPoints --remove all of the screen objects display.remove(turretBase) display.remove(turretBarrel) display.remove(target) display.remove(upButton) display.remove(downButton) display.remove(fireButton) --display the 'game over' sign gameOver = display.newText("GAME OVER!", 140, 135, "Segoe UI", 60 ) gameOver:setFillColor( 200,0,0 ) --gameOver:addEventListener('touch', closeDownApp) end --check if the target has been hit if (targetHit == true) then targetHit = false playerPoints = playerPoints + 5 timeLeft = timeLeft +100 Hit = display.newImage('Hit.png', target.x-65, target.y-65) Hit:scale( 0.3, 0.3) --replace the target with the hit picture transition.dissolve(Hit, target, 1000, 0) display.remove(bullet) --put the target back to a random position target.x = math.random(200, 450 ) target.y = math.random(100, 290 ) end end function onCollide(event) targetHit=true end function fire(event) --only fire at the beginning of a touch event if (event.phase == 'began') then media.playSound('bang.wav') bullet = display.newImage('cannonball.png') bullet:scale( 0.3, 0.3 ) --move the image bullet.x, bullet.y = turretBarrel:localToContent(70, 0) bullet.rotation = turretRotation --apply physics to the cannonball physics.addBody( bullet, { density=1.5, friction=0.2, radius=15 } ) --determine the appropriate ratio of horizontal to vertical force force\_x = math.cos(math.rad(turretRotation)) \* turretForce force\_y = math.sin(math.rad(turretRotation)) \* turretForce --fire the turretball bullet:applyForce( force\_x, force\_y, bullet.x, bullet.y ) end end function moveDown(event) --only move the barrel if the touch event started if (event.phase == 'began') then turretRotation = turretRotation + rotateAmt if (turretRotation \>= rotateMax) then turretRotation = rotateMax end turretBarrel.rotation = turretRotation fireButton.rotation = turretRotation end end function moveUp(event) --only move the barrel if the touch event started if (event.phase == 'began') then turretRotation = turretRotation - rotateAmt if (turretRotation \<= rotateMin) then turretRotation = rotateMin end turretBarrel.rotation = turretRotation fireButton.rotation = turretRotation end end function makeTarget( ) target = display.newImage('Plane.png') target:scale( 0.3, 0.3) target.x = math.random(200, 450) target.y = math.random(100, 290) physics.addBody(target,{density=1.0, friction=0.5, bounce=0.05, radius=15}) target.bodyType = 'static' target:addEventListener('collision', onCollide) end function Slider( ) --Slider back sliderBack=display.newImage('Slider back.png', -30, -80) sliderBack:scale(0.3, 0.3) --Slider slider=display.newImage('Slider.png', -15, 140) slider:scale(0.3, 0.3) yMin = 107; yMax = 233; local function onTouch( event ) local t = event.target local phase = event.phase if "began" == phase then -- Make target the top-most object local parent = t.parent parent:insert( t ) display.getCurrentStage():setFocus( t, event.id ) t.isFocus = true -- Store initial touch position on the actual object - prevents jumping when touched t.xStart = event.x - t.x t.yStart = event.y - t.y elseif t.isFocus then if "moved" == phase then print(t.yStart) t.y = event.y - t.xStart if (t.y \< yMin) then t.y = yMin end if (t.y \> yMax) then t.y = yMax end --t.y = event.y - t.yStart elseif "ended" == phase or "cancelled" == phase then display.getCurrentStage():setFocus( t, nil ) t.isFocus = false end end --This tells the system that the event -- should not be propagated to listeners of any objects underneath. return true end slider:addEventListener('touch', onTouch) --Slider control slider:addEventListener(' ', moveDown) --space for event listener to go slider:addEventListener(' ', moveUp) --space for event listener to go end function makeInterface( ) --up button -- upButton = display.newImage('up\_button.png') -- upButton:translate(10, 30) -- upButton:addEventListener('touch', moveUp) --down button -- downButton = display.newImage('down\_button.png') -- downButton:translate(10, 155) -- downButton:addEventListener('touch', moveDown) --fire button fireButton = display.newImage('fire\_button.png') fireButton:translate(500, 110) fireButton:addEventListener('touch', fire) --display turret parts turretBarrel = display.newImage('turretTop.png', 0, 150) turretBarrel:scale( 0.2, 0.2 ) turretBarrel.anchorX = 0.2813127413127 turretBarrel.anchorY = 0.805 turretBarrel.x = display.contentCenterX turretBarrel.x = display.contentCenterY turretBase = display.newImage('turretB.png', -230, 180) turretBase:scale( 0.2, 0.2 ) --turretBase:translate(70, 220) turretBarrel.x = display.contentCenterX turretBarrel.x = display.contentCenterY --display score scoreDisplay = display.newText( ('Points: ' .. playerPoints), 130, 0, "Segoe UI", 20 ) scoreDisplay:setTextColor( 0,0,100 ) scoreDisplay:translate(display.contentHeight, 0, 0) end --Define control structure function init( ) display.setStatusBar(display.HiddenStatusBar) background = display.newImage('bg2.png',0,10) physics = require('physics') physics.setDrawMode('normal') physics.start( ) makeInterface( ) makeTarget( ) Runtime:addEventListener('enterFrame', update) Slider( ) end --Call the code init( ) &nbsp;

[/spoiler]

I have commented out the parts I don’t need for now, and I am just keeping them there for reference.  I have also added the space for the Event Listeners to go to make the slider control the turret.

Thank you for your help.

-Oliver

P.S If it isn’t too much to ask, is there a way to get the slider (and turret) to move back to the default position when you let go of the slider, instead of staying where it is?

Thanks again!

Read the sliderButton.y value and convert it to a percentage point value.

Your final code will most likely read something like this:

local sliderCorrectedYPosition = sliderButton.y - sliderMinimumYPositionOnScreen turret.rotation = turretOffsetValue + turretRotationScale\*(slideCorrectedYPosition)

How do I do that?

I don’t understand what I need to replace in your script, exactly.

Hmmm - it’s pretty selfexplanatory to be honest.

Your slider has a .y value right? Basically all you do is say:

turret.rotation = slider.y

in an enterframe listener (so every frame), or in a touch listener (so whenever the slider is moved).

The problem is, your rotation might change way too much or too little, so you need a value to scale the effect down or up (turretRotationScale in my example), and you might need a different starting angle for the turret so you need a value like turretOffsetVale.

You will need to test with different numbers to see what you need to use as these two values.

Try this first:

turret.rotation = slider.y

And if it goes too fast try

turret.rotation = slider.y/10

If it goes too slow try

turret.rotation = slider.y * 10

Or other values. When the speed or amount of change is right, use the offset value to make sure your turret starts at the right point when the slider is at its lowest or highest point, depending on your specific needs.

turret.rotation doesn’t exist, so I assume it has to be :

turretBarrel.rotation = slider.y/10

And what do I do with 

turretOffsetValue = turretRotationScale\*(sliderCorrectedYPosition)

?

Thanks for your help.  I know I’m a real newbie at this xD

No problem.

You can simplify things without any bad consequences.

Just try:

turretBarrel.rotation = 100 + slider.y/10

Without anything else. Change the 10 into other numbers until you are about pleased with the amount of change. Then change the 100 (maybe even into a negative number) to get the start angle of your turretBarrel right.

When I do that the turretBarrel starts off in this position:[spoiler]
cfd6bb8110.png

[/spoiler]

The code I now have looks like this:

[spoiler]

function Slider( ) --Slider back sliderBack=display.newImage('Slider back.png', -30, -80) sliderBack:scale(0.3, 0.3) --Slider slider=display.newImage('Slider.png', -15, 140) slider:scale(0.3, 0.3) yMin = 107; yMax = 233; local function onTouch( event ) local t = event.target local phase = event.phase if "began" == phase then -- Make target the top-most object local parent = t.parent parent:insert( t ) display.getCurrentStage():setFocus( t, event.id ) t.isFocus = true -- Store initial touch position on the actual object - prevents jumping when touched t.xStart = event.x - t.x t.yStart = event.y - t.y elseif t.isFocus then if "moved" == phase then print(t.yStart) t.y = event.y - t.xStart if (t.y \< yMin) then t.y = yMin end if (t.y \> yMax) then t.y = yMax end elseif "ended" == phase or "cancelled" == phase then display.getCurrentStage():setFocus( t, nil ) t.isFocus = false end end --This tells the system that the event -- should not be propagated to listeners of any objects underneath. return true end slider:addEventListener('touch', onTouch) --Slider control turretBarrel.rotation = 100 + slider.y/10 end&nbsp;

[/spoiler]

Hi - I don’t read other people’s code because it takes too long. Sorry. I did, however tell you to first change the “10” value to get the right amount of change, and then after that change the “100” value from my sample code to change the start angle of the barrel.

So, if the start angle is wrong, change the first value. But like I said, FIRST change the “10” value to get the change amount right, and after that the other value.

Looking at your screenshot there is an alternative that could be easier.

Do you have a “start angle” for the barrel when the slider is in the middle, and then depending on wether you move up or down does the angle change? Or is the start angle when the slider is at the bottom or top?

If the basic start angle is when the slider is in the middle, could you give me the .y value for the slider when it is in the middle?

changing the /10 does very, very little, so I set it to turretBarrel.rotation = -8 + slider.y/21.  And also, moving the slider doesn’t move the turret, it stays stationary.

Some issues:

  1. Do you want to move the turret or rotate the barrel?

  2. The BIGGER you make the 10 value, the smaller the amount of change. so slider.y/2 will have a 10 times bigger effect than slider.y/20

The slider starts in the middle, and the code to input the slider is here:

--Slider slider=display.newImage('Slider.png', -15, 140) slider:scale(0.3, 0.3)

I want to rotate the barrel to shoot at the planes.  I have previously stated that I can control the barrel with some buttons, the code for that is already in place.  But they are difficult to use, so I opted for a slider.

Okay. So the default .y position in the middle is 140 pixels.

Try this code then:

turretBarrel.rotation = 90 + (slider.y-140)*0.5

Change the 90 into whatever you want to be the starting angle of the turretBarrel and change the 0.5 value to adjust the amount of change in the rotation when you slide. Watch out: in this code the bigger you make the 0.5 value, the bigger the effect will be!

Let me know how that works for you!

Okay, I have put in the code, and the barrel is in the place I want it.  But sliding the slider still doesn’t move the barrel.

Can you debug using a print statement?

Just use:

print(slider.y) in your enterFrame or touch listener and see if the console outputs the y value - we’ll take it from there.

Like this?

slider:addEventListener('touch', onTouch, print(slider.y))

Just add the print statement in your existing touch listener under both "if event.phase == “began” and if event.pahse == “moved”

Did I add it right?

Hello?

hi,

Adding a touch eventListener is extremely well documented in numerous tutorials on this site, so no need for me to repeat it here, but here it goes anyway:

It should be something like

slider:addEventlistener("touch", sliderTouched)

Note the use of double brackets, not single brackets.

This code adds a touch eventListener to the image object slider that calls a function called sliderTouched. You are of course free to name your function something else.

The put a print statement somewhere in your touch-eventListener function somewhere so you can check where things work or go wrong like this:

local function sliderTouched(event) if event.phase == "began" then print(slider.y) turretBarrel.rotation = 90 + (slider.y - 140)\*0.5 elseif event.phase == "moved" then print(slider.y) turretBarrel.rotation = 90 + (slider.y - 140)\*0.5 end end -- sliderTouched