First Time Programming - Require TLC and Assistance

Hi,

Long time stalker, first time poster.

I’ve been interested in programming something and wanted to do a game for my iPad. Did alot of research and come across Corona SDK and thought it would be easier than cocoa etc…

I’ve decided to do my first game as a Missile Command clone… thought it would be easy :slight_smile: I’ve been through a few tutorials from Peach which has helped me get to where I am but Im having troubles with some math. I have an image of a missile that shoots out from a space station from the centre bottom of the screen. Im using a transition.to to move the image from teh station to the “tap” event which works fine and dandy but the problem I am having is working out the angle to rotate the image so the missile points towards where its going. I’ve restricted the game to iPad res only (1024,768) and in landscape (home button to the left). Below is the code i have so far… doing each little bit and as i learn to do something better, replace the code out. I have a basic scoreboard happening too… it increases when I click on the station for now.

I think I need to change the missile dynamics to use physics to give a linear velocity so when you click close to the station it travels at the same speed as if you click far away from it… transition.to makes it go slow or fast depending on the distance from the station.

[code]

– Missile Command Clone –

– Have to start somewhere!

– Hide status bar
display.setStatusBar(display.HiddenStatusBar)

– Required
require (“physics”)

– Global Variables
myScore = 0

– Start physics engine and set options
physics.setGravity( 0 , 0 )
physics.start()

– Setup background image
local background = display.newImage (“background.png”)
background.x = display.contentWidth /2
background.y = display.contentHeight / 2

– Setup station.png picture on screen
local station = display.newImage( “station.png” )
station.x = display.contentCenterX
station.y = 690

– Setup Scoreboard and Text
local scoreBoard = display.newRect( 40, 700, 200, 40)
scoreBoard:setFillColor( 255, 255, 200, 70 )
scoreBoard:setStrokeColor( 255, 0, 0 )
myScoreText = display.newText( “0”, 200, 706, “Helvetica” ,25 )
myScoreText:setTextColor( 255, 255, 255 )

– Update the score on the scoreboard
function updateScore( event )
myScore = myScore + 1
myScoreText.text = myScore
end

– Shoot the missile
function shoot ( event )
print (event.x, event.y)
if event.y < 690 then
smMissile = display.newImage(“smMissile.png”)
smMissile.x = display.contentCenterX
smMissile.y = 690
transition.to(smMissile, {x=event.x, y=event.y, onComplete=kill} )
else
end
end

function kill (event)

smMissile:removeSelf()

end

–Event Listeners
station:addEventListener (“tap”, updateScore)
background:addEventListener (“tap”, shoot)

[/code] [import]uid: 83851 topic_id: 13987 reply_id: 313987[/import]

you may use the below code

[lua]radians = math.atan2(event.y-station.y,event.x-station.x);
degrees = (radians/math.pi)*180;
smMissile.rotation = degrees;[/lua]

Hope this helps…

one more thing I noticed about your code…will you be shooting multiple missiles at a time ? then you may have problem with your kill function. (currently i saw such a behavior while running your code) [import]uid: 71210 topic_id: 13987 reply_id: 51499[/import]

Yes you are right about firing off multiple missiles… that was on my next lot of research to try and solve. I try and exhaust my options before posting about it. :slight_smile: [import]uid: 83851 topic_id: 13987 reply_id: 51502[/import]

you get to solve certain things with out much research… :slight_smile:

[lua]----------------------------------------------
– Missile Command Clone –

– Have to start somewhere!

– Hide status bar
display.setStatusBar(display.HiddenStatusBar)

– Required
require (“physics”)

– Global Variables
myScore = 0

– Start physics engine and set options
physics.setGravity( 0 , 0 )
physics.start()

– Setup background image
local background = display.newImage (“background.png”)
background.x = display.contentWidth /2
background.y = display.contentHeight / 2

– Setup station.png picture on screen
local station = display.newImage( “station.png” )
station.x = display.contentCenterX
station.y = 690

– Setup Scoreboard and Text
local scoreBoard = display.newRect( 40, 700, 200, 40)
scoreBoard:setFillColor( 255, 255, 200, 70 )
scoreBoard:setStrokeColor( 255, 0, 0 )
myScoreText = display.newText( “0”, 200, 706, “Helvetica” ,25 )
myScoreText:setTextColor( 255, 255, 255 )

– Update the score on the scoreboard
function updateScore( event )
myScore = myScore + 1
myScoreText.text = myScore
end

– Shoot the missile
function shoot ( event )
print (event.x, event.y)
if event.y < 690 then
local smMissile = display.newImage(“smMissile.png”)

radians = math.atan2(event.y-station.y,event.x-station.x);
degrees = (radians/math.pi)*180;
smMissile.rotation = degrees;

smMissile.x = display.contentCenterX
smMissile.y = 690
transition.to(smMissile, {x=event.x, y=event.y, onComplete=function() smMissile:removeSelf() end} )
end
end

–Event Listeners
station:addEventListener (“tap”, updateScore)
background:addEventListener (“tap”, shoot)[/lua]

by just making the missile objects to local there will be a separate instance of missile created on each click…
being local the the missiles won’t be reachable in the kill function so i just changed it to inside the transition.to itself.
[import]uid: 71210 topic_id: 13987 reply_id: 51504[/import]

Works like a dream… I dont know if its cause i lock thescreen to landscape but I had to change your math to add 90deg to get the picture to align correctly.

degrees = ((radians/math.pi)\*180)+90;  

All works well! Thank you for your help… saved me a heap of time for sure.

Onto the rest… thanks again.
[import]uid: 83851 topic_id: 13987 reply_id: 51522[/import]

Oh… that’s just bcoz your missile was vertical mine was horizontal… :slight_smile:
[import]uid: 71210 topic_id: 13987 reply_id: 51532[/import]

I’ve managed to progress a fair bit since the last post…

Have used the director class to do a menu screen, pause screen and game over screen. Still to do the next level screen and stats/score details.

One thing to confirm though, when using the director class to transition from one screen to the other… does it clean up all the info from the old screen? ie: if I go from the game.lua to endgame.lua… do all my instances and data etc get cleaned up?

Cheers,

Adrian

[import]uid: 83851 topic_id: 13987 reply_id: 52058[/import]

if you have added all the display objects to the local group returned as part of director then it will be removed automatically. also all event listeners attached to those objects will also be removed automatically. but you should take care of those Runtime event listeners, timers and transitions you have added by yourself.
:slight_smile:
[import]uid: 71210 topic_id: 13987 reply_id: 52062[/import]

I removed all my runtime:eventlisteners but now I know why the missiles are staying on the screen when i get to the “End Game” Screen… need to kill off the transitions :slight_smile: Now to find out how to do it. [import]uid: 83851 topic_id: 13987 reply_id: 52067[/import]

you need to create a handle for your transitions… if you have many transitions u can use table for storing handle.

so its something like
transitions[i] = transition.to(…

to remove it use
transition.cancel(transition[i])
you cannot blame the transitions if you still can see your missiles in the game over screen… just make sure that those missiles are added to the local group returned from the new() function.

hope this is clear…
Happy Coding :slight_smile: [import]uid: 71210 topic_id: 13987 reply_id: 52069[/import]

Clear as mud but I thnk I know what you mean.

I’ll give it a go and see what happens.

thanks for your help again. [import]uid: 83851 topic_id: 13987 reply_id: 52070[/import]

Probably a reason why I dont like programming… frustrating as all hell… suprised I got this far though… shows Corona is good :slight_smile:

I get the below when I try what you said… or my understanding of what you said is more the point…

Runtime error
H:\Ados\Corona\MC\Main\game.lua:148: attempt to index global ‘transitions’ (a nil value)
stack traceback:
[C]: ?
H:\Ados\Corona\MC\Main\game.lua:148: in function <h:>\game.lua:132> ?: in function <?:215> [import]uid: 83851 topic_id: 13987 reply_id: 52072[/import] </h:>

did you declare i as variable and transitions as a table ?
[import]uid: 71210 topic_id: 13987 reply_id: 52104[/import]

i = nil
transitions = {}

correct?

these should be put at the top of the “new” function (director requirement) since they are being accessed by various functions.

Still trying to wrap my head around some syntax… this is my first programming effort… be nice :slight_smile: Im 37… brain doesnt work too well with learning new things. :slight_smile: My excuses anyway. :slight_smile:

Thanks again for your time and help.

Regards,

Adrian [import]uid: 83851 topic_id: 13987 reply_id: 52232[/import]

Adrian,
I think you will get a better idea looking at this. :slight_smile:

http://blog.anscamobile.com/2011/08/corona-sdk-memory-leak-prevention-101/ [import]uid: 71210 topic_id: 13987 reply_id: 52248[/import]

Just a quick note - you need to cancel only those transactions and timers which are still running when you are switching the screen, you don’t need to cancel transitions and timers that have completed. [import]uid: 71210 topic_id: 13987 reply_id: 52251[/import]

I added the transitionStash as mentioned in the article you posted but its dawned on me that display objects added to the display groups will get cleaned up by director when switching scenes. You mentioned it in post#7 but it didnt click until now. I think I’m still running a 486 upstairs. =\

So i added the spawned missile objects to the displaygroup and now they get cleared up…

*sigh*

Added some extra effects when the level starts to show what level it is… I’m now going to add the code to begin the bombardment of asteroids towards the spacestation. I still need to add collision code etc.

Is it safe to make the asteroids into a physics body for the collision detection but still use the transition.to for the movement?

Regards,

Adrian [import]uid: 83851 topic_id: 13987 reply_id: 52286[/import]

My messy game.lua code as it stands.

[lua]module(…, package.seeall)

function new()

–local group for Director
local localGroup = display.newGroup()

local physics = require (“physics”)
– Start physics engine and set options
physics.setGravity( 0 , 0 )
–physics.setDrawMode( “hybrid” )
physics.start()

– Setup Display Groups
local bkgdGroup = display.newGroup()
local frgdGroup = display.newGroup()
local scoreGroup = display.newGroup()

– Setup background image
local bkgd = display.newImage (“background.png”)
– Setup foreground images
local station = display.newImage(“station.png”)
local pausebtn = display.newImage(“pause.png”)

– Display Group For Background Images
bkgdGroup:insert(bkgd)
bkgdGroup:setReferencePoint(display.CenterReferencePoint)
bkgdGroup.x = _W / 2; bkgdGroup.y = _H / 2;

– Displayground for foreground images
frgdGroup:insert(station)
station.x = _W / 2; station.y = _H - 100;
frgdGroup:insert(pausebtn)
pausebtn:setReferencePoint(display.BottomRightReferencePoint)
pausebtn.x = _W - 30; pausebtn.y = _H - 25; pausebtn.alpha = 0.5;

– Setup Scoreboard
local scoreBoard = display.newRect(0, 0, 200, 40)
– Preset Settings for disaply objects
scoreBoard:setFillColor(255, 255, 200, 70)
local myScoreText = display.newText(“0”, 0, 0, native.systemFont, 30)
myScoreText:setTextColor(255, 255, 255)
myScoreText:setReferencePoint(display.TopLeftReferencePoint)
myScoreText.x = 165; myScoreText.y = 4;

– Display Group for ScoreBoard
scoreGroup:insert(scoreBoard)
scoreGroup:insert(myScoreText)
scoreGroup:setReferencePoint(display.BottomLeftReferencePoint)
scoreGroup.x = 30; scoreGroup.y = _H - 25;

–Setup shield around station
shield = display.newImage(“shield_1.png”)
shield.myName = “shield”
frgdGroup:insert(shield)
shield.x = _W / 2 - 6; shield.y = _H - 100;
physics.addBody(shield, “static”, {density=1, friction=0, bounce=0, radius=78})

– Shoot listener function
function shootListener ()
function addShootListener()
bkgd:addEventListener (“tap”, shoot)
physics.start()
end
timer.performWithDelay( 300, addShootListener,1 )
end

– pause screen popup
local function pauseScreen( event )
if event.phase == “ended” then
bkgd:removeEventListener (“tap”, shoot)
physics.pause()
director:openPopUp( “pause”, shootListener)
end
end

– Update the score on the scoreboard
local function updateScore( event )
_MyScore = _myScore + 10
myScoreText.text = _MyScore
end

– Update shot data
local function updateShots ()
_ShotsFired = _ShotsFired + 1
end

– Update number of objects destroyed
local function updateDestroyed ()
_NumDestroyed = _NumDestroyed + 1
– End the game if the destroyed targets meets criteria
if _NumDestroyed == _ToDestroy then
endGame()
end
end

– When game ends, display game over graphis
– Show score, shots fired and number of object destroyed… dig i mention chicks dig it?
local function endGame ()
– Clean Up
bkgd:removeEventListener (“tap”, shoot)
cancelAllTransitions()
physics.stop()
– Display gameover dialogue
director:changeScene(“gameover”)
end

– Missile explosion at end of transition
local function msExplosion(x,y)
local explosion = display.newCircle(0,0,5)
frgdGroup:insert(explosion)
explosion.x = x; explosion.y = y; explosion.alpha=0.6;
explosion:setFillColor ( 255, 240, 0 )
local rand = math.random(15,25)
transitionStash.newTransition=transition.to(explosion, {time=1500, xScale=rand, yScale=rand, onComplete=function()explosion:removeSelf();updateDestroyed();end})
end

– Launch objects towards station from
– random locations across the top of the screen
local function deployAsteroid ()
local asteroid = display.newImage(“asteroid.png”)
asteroid.myName = “asteroid”
frgdGroup:insert(asteroid)
asteroid:setReferencePoint(display.CenterReferencePoint)
asteroid.x = math.random(-30, 1054); asteroid.y = -20;
asteroid.xScale = 0.75; asteroid.yScale = 0.75;
physics.addBody(asteroid, {density=1, friction=0, bounce=0, radius=47})
transitionStash.newTransition=transition.to(asteroid, {time=6000, x = _W / 2, y = _H-100, rotation= 180, onComplete=function()asteroid:removeSelf();end})
end

– Shoot the missile
function shoot ( event )
if event.y < (_H - 125) then
– update how many shots to have fired
updateShots()
– Initialize missile.png on screen
local smMissile = display.newImage(“smMissile.png”)
smMissile.myName = “missile”
frgdGroup:insert(smMissile)
– Maths… I hate it
radians = math.atan2(event.y-station.y,event.x-station.x)
degrees = ((radians/math.pi)*180)+90
– Maths… Rotate it
smMissile.rotation = degrees
– Missile launch location (on space station)
smMissile.x = display.contentCenterX
smMissile.y = 690
– Move missle from station to touch event… Vrooooom!
transitionStash.newTransition = transition.to(smMissile, {x=event.x, y=event.y, transition=easing.inQuad, onComplete=function() smMissile:removeSelf(); msExplosion(event.x,event.y); end})
end
end

local function depleteShield()
local function killShield()
shield = display.newImage(“shield_2.png”)
shield.myName = “shield”
frgdGroup:insert(shield)
shield.x = _W / 2 - 6; shield.y = _H - 100;
physics.addBody(shield, “static”, {density=1, friction=0, bounce=0, radius=78})
end
transitionStash.newTransition = transition.to(shield, {time=300, alpha = 0, onComplete= function() display.remove(shield); end})
timer.performWithDelay(300,killShield)
end

local function onCollision(e)
– Detect if the collision is from the asteroid hitting the station or a missile explosion
if (e.object2.myName == “asteroid”) and (e.phase == “began”) then
if _ShieldNo <= 5 then
_ShieldNo = 2
print(“Hit Detected”)
depleteShield()
–Insert code to remove asteroid here–
else
gameOver()
end
else if (e.object2.myName == “missile”) and (e.phase == “began”) then
msExplosion()
end
end
end

local function launchGame()
– check level number and increase items
– to be destroyed as game progresses
if _MyLevel == 1 then
_MyScore = 0
_ShotsFired = 0
_NumDestroyed = 0
_ToDestroy = 5
else
_ToDestroy = _toDestroy + math.random(5,8)
end

–Display what level you are onat start of game
local levelText = display.newText(("Level "… _MyLevel),0,0, “Bauhaus 93”, 140)
frgdGroup:insert(levelText)
levelText:setTextColor(255,255,255)
levelText.x = _W / 2
levelText.y = _H / 2
transitionStash.newTransition = transition.to(levelText, {time=1000, delay=1000, alpha=0, onComplete=shootListener})
local rnumb = math.random(2000,3500)

– insert code to deploy asteroids until _ToDestroy number has been met –
timer.performWithDelay(rnumb, deployAsteroid)
end

–Launch the game
launchGame()

–Pause Event Listeners
pausebtn:addEventListener(“touch”, pauseScreen)
Runtime:addEventListener(“collision”, onCollision)

localGroup:insert(bkgdGroup)
localGroup:insert(frgdGroup)
localGroup:insert(scoreGroup)

return localGroup

end[/lua] [import]uid: 83851 topic_id: 13987 reply_id: 53006[/import]