Tutorial 7 - MineSweeper Game Part 2

Part 2 of the MineSweeper game tutorial is up now at http://codeatuts.blogspot.com.au/

This looks at the code in detail and adds high score functionality.

Additional suggestions, comments and corrections are very welcome!

@Reefwing, I have just finished laboriously downloading each class of the Minesweeper tutorial, v.2, via Safari, Goodreader, and finally pasting each class into a Codea tab. It all looks good, but when I try to run it, it comes up with the “Hello World” print statement and a black screen, like a new project from template. It then does nothing until I tap on the screen, at which point it gives me an error message stating that easyButton is undefined and nil. First of all, there is no “Hello World” print statement in the Minesweeper main, and secondly, it doesn’t seem to see any of the setup statements prior to the creation of easyButton. I moved the definition of Splashscreen up so it came before any button creation, and I added a print statement above that to display the value of gameState, but neither the Minesweeper version print statement nor mine display when I run it. I suspect something got corrupted in the download, but I can’t tell what. I tried copying the whole project and deleting the original and I tried exiting and clearing Codea and all other loaded apps from memory, but that hasn’t helped, either. What do you or @Simeon suggest?

I’m also puzzled as to why this posting font is turning up. It looks normal when I’m typing it, but when I post it goes all bold and large. Sorry about that.

No problem about the formatting issue — it’s because you accidentally used ‘#’ to signify a username instead of ‘@’ (I’ve corrected it)

@NancyW just to sanity check that @reefwing’s code works for you, have you tried downloading his single file version of the Minesweeper code:

https://www.dropbox.com/s/ai6pz84xz9rfymc/Tutorial_7_MineSweeper_v1_2.lua

And pasting it into a new project? Note that you must replace the entire contents of the existing Main tab with the file linked above.

See if that works for you (it should be much quicker to try than what you have already done — copy and paste the files individually).

Hi @NancyW,

Well done on all the copying and pasting! It sounds like you almost have it working. The fact that you get an error message when you tap the screen means that the button has not been loaded in setup() but the touched function is working. The fact that the version info isn’t being printed also supports this.

Doing what @Simeon suggests should get you a working version. From there you can cut and paste each class into a separate tab. Do it one class at a time and test that it still works after each paste. That is my normal approach to trying out code from the forums.

Alternatively, paste the setup() and draw() functions here from your Main tab and we can have a look at it. Are you sure that you pasted over all of the contents of the default project?

There will be a reason for what you are seeing, there always is. Welcome to debugging!

Thanks for your help, @Simeon and @Reefwing. I’ll try redoing Main as you suggested. Believe me, I have many years of debugging experience. Is there any chance of a step-by-step debugger in Codea? Or break points? That would really help isolate problems.

Thanks, I found the problem. @Reefwing was right. Way down at the end was some of the template Main. I removed it and everything worked.
I suppose we can’t have step-by-step debugging, what with the “invisible” Codea interface executing the draw function 60 times a second, but break points would help.

. @NancyW - excellent and sorry about making assumptions about your experience, I should know better than that.

I have an updated version (v1.3) of Minesweeper which adds support for orientation changes, is prettied up a bit and is in a form suitable for use in the runtime (ie no dependencies). I will post the code and associated assets for this once I have ironed out all of the submission wrinkles.

@Reefwing can’t wait to see v1.3. I’m so confused about how to deal with orientation change. I’m using the same button class your using so hopefully mine will get worked out. You’re awesome @Reefwing and hope to see submitting to the app store part 2 and your new Minesweeper version. I’m getting a MacBook pro tmrw and I’ll give your tutorial a shot as soon as I receive ut and download Xcode. btw, does Xcode come with the iOS simulator

. @veeeralp - thanks dude, I appreciate the kind words. Yes the iOS simulator comes with Xcode.

Here are the relevant functions from Minesweeper, you should be able to work it out from that, you will need to put in support orientations ANY at the start as well.

function drawGameButtons()
    
    -- These are the buttons visible on the game run screen
    
    local mButtonSize = vec2(100, 50)
    if CurrentOrientation == LANDSCAPE_LEFT or CurrentOrientation == LANDSCAPE_RIGHT then
        mLocX = WIDTH - 200
        mLocY = HEIGHT - 195
    else
        mLocX = WIDTH - 125
        mLocY = HEIGHT - 320
    end
    
    flagButton.x, flagButton.y = mLocX, mLocY
    
    if CurrentOrientation == LANDSCAPE_LEFT or CurrentOrientation == LANDSCAPE_RIGHT then
        mLocY = 110 + mButtonSize.y*2
    else
        mLocY = 240 + mButtonSize.y*2
    end
    
    newGameButton.x, newGameButton.y = mLocX, mLocY
    
    if CurrentOrientation == LANDSCAPE_LEFT or CurrentOrientation == LANDSCAPE_RIGHT then
        mLocY = 110
    else
        mLocY = 240
    end    
        
    menuButton.x, menuButton.y = mLocX, mLocY
    
    flagButton:draw()
    newGameButton:draw()
    menuButton:draw()
    
end

-- Handle iPad Orientation Changes

function updateGridLocation()
    
    -- This function is required to reposition the grid
    -- if the iPad orientation changes.
    
    local baseX = WIDTH/2 - (iconSize * gridWidth) / 2
    local y = HEIGHT/2 - (iconSize * gridHeight) / 2
    local x = baseX
    
    for i = 1, gridWidth do
        for j = 1, gridHeight do
            grid[i][j].pos.x = x
            grid[i][j].pos.y = y
            x = x + iconSize
        end
        x = baseX
        y = y + iconSize
    end
    
end

function orientationChanged(newOrientation)
    
    if gameState == stateRun or gameState == stateWon or gameState == stateLost then
        updateGridLocation()
    end 
    
end

did you include the position for the buttons in the setup() function. I have mLocX and mLocY in my setup function tool should I remove that. Here’s an example

   local mButtonSize = vec2(180, 50)
   local mLocX = WIDTH/2 - mButtonSize.x/2
   local mLocY = HEIGHT/2 + 95

   HowToPlayButton = Button("How to Play", vec2(mLocX, HEIGHT/2 + 176), mButtonSize.x, mButtonSize.y)
   HowToPlayButton.action = function() HowToPlayButtonPressed() end
   
   mLocY = mLocY - 80
   easyButton = Button("Easy", vec2(mLocX, mLocY), mButtonSize.x, mButtonSize.y)
   easyButton.action = function() easyButtonPressed() end

   mLocY = mLocY - 80
   mediumButton = Button("Medium", vec2(mLocX, mLocY), mButtonSize.x, mButtonSize.y)
   mediumButton.action = function() mediumButtonPressed() end

   mLocY = mLocY - 80
   hardButton = Button("Hard", vec2(mLocX, mLocY), mButtonSize.x, mButtonSize.y)
   hardButton.action = function() hardButtonPressed() end
  
   mLocY = mLocY - 80
   tiltButton = Button("Tilt", vec2(mLocX, mLocY), mButtonSize.x, mButtonSize.y)
   tiltButton.action = function() tiltButtonPressed() end
 
   mLocY = mLocY - 80
   timetrialButton = Button("Time Trial", vec2(mLocX, mLocY), mButtonSize.x, mButtonSize.y)
   timetrialButton.action = function() timetrialButtonPressed() end

   mButtonSize = vec2(330, 50)
mLocX = WIDTH/2 - mButtonSize.x/2
   mLocY = mLocY - 78
   resumeButton = Button("", vec2(mLocX, mLocY), mButtonSize.x, mButtonSize.y)
   resumeButton.action = function() resumeButtonPressed() end
   
   menuBorder = RoundBorder(10, 10, WIDTH - 10, HEIGHT - 10, 1, blueColour, blackColour)

   -- create the run screen buttons

   mLocX = WIDTH - mButtonSize.x/2 - 11
   mLocY = HEIGHT - 195
   mButtonSize = vec2(100, 50)
   mLocY2 = HEIGHT/2 -225
   mLocX2 = WIDTH/2 +15
   
   mLocX3 = WIDTH/2 -115



   newGameButton = Button("", vec2(mLocX2, mLocY2), mButtonSize.x, mButtonSize.y)
   newGameButton.action = function() newGameButtonPressed() end


   menuButton = Button("", vec2(mLocX3, mLocY2), mButtonSize.x, mButtonSize.y)
   menuButton.action = function() menuButtonPressed() end

   mLocY = 1
   pauseButton = Button("PAUSE", vec2(WIDTH - mButtonSize.x/2 - 51, mLocY), mButtonSize.x, mButtonSize.y)
   pauseButton.action = function() pauseButtonPressed() end

.@Reefwing I posted your code into v1.2 of minesweeper and noticed that you have the same problem I have when I load the easy game in landscape orientation and switch it to portrait, the buttons disappear off the screen. I’m pretty sure I posted the code in the correct place and I also made the game full screen. I have to restart the program in the portrait orientation to get the buttons to show up. Let me know if you also experience with your code. This is what I have to do in my game too.

. @veeeralp - works fine in my version. You can change the orientation at anytime and the buttons move appropriately. I will post a link to the complete code tonight.

.@Reefwing are you in Australia or something because here in the US it’s almost midnight. So tonight means tomorrow morning for me. Just wondering so I don’t sit around on my iPad all night checking if uploaded the code

yep I’m in Australia.

. @veeeralp - here is the link for version 1.3:

https://www.dropbox.com/s/7zto5gbv0v3rfbj/Tutorial_12_MineSweeper_v1_3.lua

You will need to replace the custom sprite images with your own (with similar dimensions).

.@Reefwing what algorithm did you use to convert the landscape orientation coordinates to look properly on portrait. Did you subtract by something? I can’t tell and get it to work on my buttons

Hi @veeeralp - I used the “trial and error” algorithm. :wink:

It depends what else you have on the screen so there is no general algorithm. The easiest way to make it work in both orientations is to put your buttons right in the middle which is what I did for the menu. In most cases this isnt practical so you will just need to play around till you get something that looks good in both orientations. You know the width and height in both circumstances (they just swap) so it shouldnt be too hard to work out what co-ordinates will work. Don’t forget that the buttons are drawn from their bottom left hand corner so you will need to take the button width into account.

@Reefwing alright cool. I’ll try it out. Hopefully it won’t take too long. Did you think about making minesweeper universal I made a post about it and am gonna try it with my game. Also, when is part 2 of submitting an app to the AppStore coming out. I’m really looking forward to it as I’m getting a macbook pro tomorrow evening

edit: I tried it out and it’s not working for my game. I have a question though. When I was making my game I positioned the buttons so that they would appear on the screen no matter what position it was in. But the only problem was that the buttons would get messed up if the orientation was changed while the game was running. So when I got into my new orientation I just pressed the restart button and the buttons would be drawn correctly. Is there a way I could get the buttons to be redrawn when I change the orientation to the correct width and height. This way I don’t have to adjust the coordinates manually.

.@veeeralp - part 2 due out tomorrow. No plans to make it universal, I suspect you would need to tweak the runtime as well to make this work. I’m sure you will enjoy the MacBook Pro although if you are a long time Windows user there are some subtle differences which are frustrating at first.

Regarding your button problem I’m not sure what else to suggest. It works for me! You might have to post the code so I can have a look at it.