Create a Math Game

@CodingIsLife Try this. You’ll have to add code for the enter key to compare with your calculated answer and do what you need to do if correct or not.

function touched(t)
    if t.state==ENDED then --wait for touch to end
        local touch=vec2(t.x,t.y)
        for i=0,9 do
            if touch:dist(buttons[i].pos)<75 then
                keyTouched=i
                value=value*10+i
                return
            end
        end
        if touch:dist(vec2(WIDTH/2-250,HEIGHT/2-300))<75 then   -- clear
            value=0
        end
        if touch:dist(vec2(WIDTH/2-50,HEIGHT/2-300))<75 then    -- backspace
            value=value//10
        end
        if touch:dist(vec2(WIDTH/2+50,HEIGHT/2+130))<75 then    -- enter
            -- compare value with answer then move 0 to value
            value=0
        end
        
    end
end

Dave’s solution is good, but in the interest of neatness, you can store button values for clear, backspace, etc, just as you did with the number keys, eg

buttons["clear"].pos=vec2(WIDTH/2-250, HEIGHT/2-300, 75)
buttons["clear"].img="Project:clearButton"

You see that a table can mix numbered items (0-9) with (text) named items.

Then in draw, you can alter your code slightly to draw all your buttons in one loop. This version of a for loop will handle a mixture of number (0-9) and text (eg “clear”) items.

for i,b in pairs (buttons) do
    sprite(b.img,b.pos.x,b.pos.y,75)
end

In touch, you can then modify dave’s code to use the table items

if touch:dist(buttons["clear"].pos)<75 then   -- clear
    value=0
end

The benefit of doing this is that all your key positions are defined in one place, and in one table, in setup, and not duplicated in draw, touch, etc. This makes it much easier to make changes. For example, if you wanted to move your whole keypad 10 pixels to the left for some reason, you could (say) define a variable offset in setup

offset=vec2(-10,0)

and then use it to modify the draw function, this easily

for i,b in pairs (buttons) do
    local p=b.pos-offset
    sprite(b.img, p.x, p.y, 75)
end

Now it’s trivial to move your keypad around the screen.

@dave1707 @Ignatz Thanks for the quick reply. I’m going to be adding the code in shortly. @Ignatz the line of code you said:

buttons["clear"].pos=vec2(WIDTH/2-250, HEIGHT/2-300, 75)
buttons["clear"].img="Project:clearButton"

is only for the clear button, correct? If so, then I’d need to repeat the process with the other two buttons, right?

Yes, do the other buttons too

@CodingIsLife Playing your program, I noticed that you still need to prevent negative answers and answers with a decimal point. So far it’s looking good.

@Ignatz Thanks @dave1707 Yeah I was debating whether to implement a decimal button and a negative/minus button. It really all depends on how easy it would be to accomplish to be honest. I suppose it’s a possibility, but I’d rather prevent them. Another thing to figure out.

@Ignatz Also would I put

buttons["clear"].pos=vec2(WIDTH/2-250, HEIGHT/2-300, 75)
buttons["clear"].img="Project:clearButton"

Under/in the

buttons={}
    for i=0,9 do
    buttons[i]={} 
    buttons[i].img="Project:button"..i
    buttons[i].pos=vec2(WIDTH/2,HEIGHT/2)+pos[i]
    end

Code?

Yes, put it under that loop (NOT inside it)

@Ignatz Okay well I’ve done the clear and backspace button but I get an error on line 73

error: attempt to index a nil value (field ‘clear’)

Line 73:
value=value*10+i

My touch function

function touched(t)
    if t.state==ENDED then --wait for touch to end
        local touch=vec2(t.x,t.y)
        for i=0,9 do
            if touch:dist(buttons[i].pos)<75 then
                keyTouched=i
                value=value*10+i
                return
            end
        
            if touch:dist(buttons["clear"].pos)<75 then   -- clear
               value=0
            end
        
            if touch:dist(buttons["backspace"].pos)<75 then   -- backspace
                value=value//10
            end
        end
    end
end

Here is the other code

buttons={}
    for i=0,9 do
    buttons[i]={} 
    buttons[i].img="Project:button"..i
    buttons[i].pos=vec2(WIDTH/2,HEIGHT/2)+pos[i]
    end
end
 -- List of positions for the clear, backspace and enter buttons
buttons["clear"].pos=vec2(WIDTH/2-250, HEIGHT/2-300, 75)
buttons["clear"].img="Project:clearButton"
buttons["backspace"].pos=vec2(WIDTH/2-50, HEIGHT-300, 75)
buttons["backspace"].img="Project:backspaceButton"
buttons["enter"].pos=vec2(WIDTH/2+50, HEIGHT+150, 75)
buttons["enter"].img="Project:enterButton"

Try putting this line before you set all the positions for these buttons

buttons["clear"],buttons["backspace"],buttons["enter"]={},{},{}

@Ignatz That only gets rid of everything on the screen

 -- MathGame

    supportedOrientations(LANDSCAPE_ANY)
    --displayMode(FULLSCREEN)

    -- Use this function to perform your initial setup
    function setup()
        value = 0
        create()
        noFill()
        noSmooth()
        noStroke()
       pushStyle()
     -- Sprites in variables  
        right=0
        wrong=0
    clearButton = "Project:clearButton"
    backspaceButton = "Project:backspaceButton"
    enterButton = "Project:enterButton"
    professor = "Project:professor"
    speechBubble = "Project:speechBubble"
   -- List of positions for the keypad
         local pos =   {vec2(-250,0),vec2(-150,0),vec2(-50,0),vec2(-250,-100),vec2(-150,-100),ve  c2(-50,-100),vec2(-250,-200),vec2(-150,-200),vec2(-50,-200)}
    pos[0]=vec2(-150,-300)

     buttons["clear"],buttons["backspace"],buttons["enter"]={},{},{}
    
     buttons={}
        for i=0,9 do
        buttons[i]={} 
        buttons[i].img="Project:button"..i
        buttons[i].pos=vec2(WIDTH/2,HEIGHT/2)+pos[i]
        end
    
     end
     -- List of positions for the clear, backspace and enter buttons
    buttons["clear"].pos=vec2(WIDTH/2-250, HEIGHT/2-300, 75)
    buttons["clear"].img="Project:clearButton"
    buttons["backspace"].pos=vec2(WIDTH/2-50, HEIGHT-300, 75)
    buttons["backspace"].img="Project:backspaceButton"
    buttons["enter"].pos=vec2(WIDTH/2+50, HEIGHT+150, 75)
    buttons["enter"].img="Project:enterButton"

     function create()
        a={}
        ans={}
        str={}
        choice=math.random(4)
        c=math.random(4)    -- + - x /
        for z=1,4 do
        a[z]=vec2(math.random(99),math.random(99))
        if c==1 then
            str[z]=string.format("%d + %d = ",a[z].x,a[z].y)
            ans[z]=math.tointeger(a[z].x+a[z].y)
        elseif c==2 then
            str[z]=string.format("%d - %d = ",a[z].x,a[z].y)
            ans[z]=math.tointeger(a[z].x-a[z].y)
        elseif c==3 then
            str[z]=string.format("%d x %d = ",a[z].x,a[z].y)
            ans[z]=math.tointeger(a[z].x*a[z].y)
        elseif c==4 then
            str[z]=string.format("%d / %d = ",a[z].x,a[z].y)
            ans[z]=a[z].x/a[z].y
        end        
    end
    end

    -- This function gets called once every frame
     function touched(t)
        if t.state==ENDED then --wait for touch to end
            local touch=vec2(t.x,t.y)
            for i=0,9 do
                if touch:dist(buttons[i].pos)<75 then
                    keyTouched=i
                    value=value*10+i
                    return
                end
            
            if touch:dist(buttons["clear"].pos)<75 then   -- clear
               value=0
            end
            
            if touch:dist(buttons["backspace"].pos)<75 then   -- backspace
                value=value//10
            end
        end
    end
    end

    -- This function gets called once every frame
     function draw()
    
    -- This sets a dark background color 
    background(40, 40, 50)
    
    -- This displays the 0-9 keypad
    for i=0,9 do
    sprite(buttons[i].img,buttons[i].pos.x,buttons[i].pos.y,75)
    end
    
    -- This displays the input rectangle correlating with the keypad
    rect(WIDTH/2-100, HEIGHT/2-300)
    
    -- This displays the backspace, clear button and enter button
    sprite(clearButton, WIDTH/2-250, HEIGHT/2-300, 75)
    sprite(backspaceButton, WIDTH/2-50, HEIGHT/2-300, 75)
    sprite(enterButton, WIDTH/2+50, HEIGHT/2+130, 75)
    
    -- This displays the "Right" and "Wrong" at the top of the screen and the increments 
    fill(255)
    fontSize(48)
    text("Right "..right,WIDTH/2-100,HEIGHT-50) -- "Right 0" 
    text("Wrong "..wrong,WIDTH/2+100,HEIGHT-50) -- "Wrong 0"
    rect(WIDTH/2-300, HEIGHT/2+100, 300, 50) -- Input bar
    
    for i,b in pairs (buttons) do
        sprite(b.img,b.pos.x,b.pos.y,75)
      end
    
    fill(0)
    text(value, WIDTH/2-150, HEIGHT/2+120)
    
    -- This displays the professor sprite and his speech bubble
    sprite(professor, WIDTH/2+225,HEIGHT/2-100, 350, 600)
    sprite(speechBubble, WIDTH/2+75, HEIGHT/2+225, 250, 150)
    
    fill(0, 0, 0, 255)
    text(str[choice],WIDTH/2+75,HEIGHT/2+230)
    end

There are at least two problems

  1. the line you just added should be just before you define the clear button position. You have added it just before the line buttons={}, which will cancel the line you have just added

  2. you have the end of the setup function in the wrong place, after the loop that sets the number buttons, and before you set the clear button

I’m going to try and fix the problems. Well problem #2 was a mistake on here rather than in the code. (Indenting issue in my comment)

Sometimes neatness isn’t the best way. Getting the program to work, #1. Understanding everything that’s happening, #2. Rewriting the code to make it better or smaller, #3.

yes, but refactoring should be happening as you go, not just at the end

I think instead of stressing over how to fix the errors I’m just going to use Dave’s code. Neatness is not my main priority now. Thanks anyways @Ignatz

This is just a small assignment and I just want to complete it. As long as it runs properly that’s all that matters.

That’s where I disagree. When the program works and you understand everything that’s happening, then you have a better idea of what needs to be changed and how to change it to make it better and smaller.