Create a Math Game

@dave1707 That makes sense in my head but I don’t know exactly how to code that perfectly. I’m very visual so examples help (in code).

(I understand why that reverse math works)

@CodingIsLife - For the division problem, it’s probably best to work backwards from the divisor, ie choose that first.

For example,

  1. randomly choose a divisor D between 0 and 50, eg 17
  2. calculate how many times N it goes into 99 evenly (which is 5 for 17)
  3. randomly choose a number R between 2 and N
  4. ask the user to divide D*R by D

Can you figure some of this code out for yourself?

You should put buttons={} just before you start allocating images and positions, and the obvious place for all that code is in setup.

for the button positions, here’s the second one

buttons[1].pos=vec2(WIDTH/2-250,HEIGHT/2)

(I’m just copying the positions you used in draw)

@Ignatz Thanks for the example. That’ll help a bunch. I’m sure I can figure out the math.random function. That step-by-step process really helps! :slight_smile:

@CodingIsLife Here’s a simple example. You can adjust the numbers in calc() to fit your needs. Keep taping the screen for another problem.

function setup()
    calc()
end

function calc()
    output.clear()
    a=math.random(25)
    b=math.random(50,99)//a
    print(a*b.." / "..a.." = "..b)
end

function touched(t)
    if t.state==BEGAN then
        calc()
    end
end

@dave1707 That works nicely. I would rather have the equations in a text function than print (if that’s even possible)

@Ignatz This is how I interpreted your comment.

 -- MathGame

-- Use this function to perform your initial setup
function setup()
supportedOrientations(LANDSCAPE_ANY)
--displayMode(FULLSCREEN)
noFill()
noSmooth()
noStroke()
pushStyle()

buttons={}
for i=0,9 do
buttons[i]={} 
buttons[i].img="Project:button"..i
end

buttons[0].pos=vec2(WIDTH/2-150,HEIGHT/2-300)
buttons[1].pos=vec2(WIDTH/2-250, HEIGHT/2)
buttons[2].pos=vec2(WIDTH/2-150,HEIGHT/2)
buttons[3].pos=vec2(WIDTH/2-50, HEIGHT/2)
buttons[4].pos=vec2(WIDTH/2-250,HEIGHT/2-100)
buttons[5].pos=vec2(WIDTH/2-150,HEIGHT/2-100)
buttons[6].pos=vec2(WIDTH/2-50, HEIGHT/2-100)
buttons[7].pos=vec2(WIDTH/2-250,HEIGHT/2-200)
buttons[8].pos=vec2(WIDTH/2-150, HEIGHT/2-200)
buttons[9].pos=vec2(WIDTH/2-50,HEIGHT/2-200)

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
                return
                print("touch") --just a test to see if it registers the touch
            end
        end
    end
end

-- This function gets called once every frame
function draw()

-- This sets a dark background color 
background(40, 40, 50)

for i=0,9 do
    sprite(buttons[i].img,buttons[i].pos.x,buttons[i].pos.y,75)
end

-- This displays the "Right" and "Wrong" at the top of the screen 
fill(255)
fontSize(48)
text("Right     ",WIDTH/2-100,HEIGHT-50)
text("Wrong     ",WIDTH/2+100,HEIGHT-50)

end

@CodingIsLife Here’s an example with text added.

function setup()
    calc()
end

function calc()
    output.clear()
    a=math.random(25)
    b=math.random(50,99)//a
    print(a*b.." / "..a.." = "..b)
end

function draw()
    background(0)
    fill(255)
    text(a*b.." / "..a.." = ",WIDTH/2,HEIGHT/2)
end

function touched(t)
    if t.state==BEGAN then
        calc()
    end
end

@dave1707 Thanks. Now I just need to randomly generate the operation and display that in an output rect and have an input rect too for the keypad.

Yes.

You can make it neater still by putting the button positions into a table, like so

local pos={vec2(-150,-300),vec2(-250,0),vec2(-150,0), etc etc}
buttons={}
for i=0,9 do
    buttons[i]={} --make subtable for each button
    buttons[i].img="Project:button"..i
    buttons[i].pos=vec2(WIDTH/2,HEIGHT/2)+pos[i]
end

The temporary pos table lists the ten screen positions of the button, leaving out WIDTh and HEIGHT because they are the same for all of them, so we can add them later.

Then our loop that sets the images, can also set the positions, avoiding the need for 10 separate statements.

@Ignatz I’ve attempted to make the list but when I press the start program button I get to errors. Screenshot line 20 is

buttons[i].pos=vec2(WIDTH/2,HEIGHT/2)+pos[i]

and line 46 is

sprite(buttons[i].img,buttons[i].pos.x,buttons[i].pos.y,75)

-- MathGame

-- Use this function to perform your initial setup
function setup()
supportedOrientations(LANDSCAPE_ANY)
--displayMode(FULLSCREEN)
noFill()
noSmooth()
noStroke()
pushStyle()

right=0
wrong=0

local pos =     {vec2(-150,-300),vec2(-250,0),vec2(-150,0),vec2(-50,0),vec2(-250,-100),vec2(-150,-100),vec2(-50,-100),vec2(-250,-200),vec2(-150,-200),vec2(-50,-200)}
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

-- 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
            return
            print("touch") --just a test to see if it registers the touch
        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 "Right" and "Wrong" at the top of the screen 
fill(255)
fontSize(48)
text("Right     ",WIDTH/2-100,HEIGHT-50)
text("Wrong     ",WIDTH/2+100,HEIGHT-50)
rect(WIDTH/2-300, HEIGHT/2+100, 300, 50)

text(right, WIDTH/2-50, HEIGHT-50)
text(wrong, WIDTH/2+175, HEIGHT-50)
end

Yes, the problem is that when we set up a table this way, it starts from 1, not 0 as we want. So what we can do is just give it the positions 1 to 9, then add position 0 afterward, like this

local pos =     {vec2(-250,0),vec2(-150,0),vec2(-50,0),vec2(-250,-100),vec2(-150,-100),vec2(-50,-100),vec2(-250,-200),vec2(-150,-200),vec2(-50,-200)}
pos[0]=vec2(-150,-300)

I’ve changed that part of the code and the “Right” & “Wrong” and the rect displays, but the number keypad does not. Although the output sidebar still prints “touch” when I tap on where they’d be.

Do your button images exist?

You don’t need them anyway, you can draw text numbers instead

--to draw them...
    fill(255) --NEW
    fontSize(24) --NEW
    for i=0,9 do
        text(i,buttons[i].pos.x,buttons[i].pos.y) --NEW
    end

For some reason it works now. I just deleted the sprite(buttons[i].img…) stuff under the draw function and retyped it

Okay so I’ve added a clear and backspace button. The next thing I want to do is when the buttons are pressed they actually do something :)) Also in case you want to see my code (anyone) this is it: (http://imgur.com/69mKCPP)

-- MathGame

-- Use this function to perform your initial setup
function setup()
supportedOrientations(LANDSCAPE_ANY)
--displayMode(FULLSCREEN)
noFill()
noSmooth()
noStroke()
pushStyle()

right=0
wrong=0

clearButton = "Project:clearButton"
backspaceButton = "Project:backspaceButton"
local pos =     {vec2(-250,0),vec2(-150,0),vec2(-50,0),vec2(-250,-100),vec2(-150,-100),vec2(-50,-100),vec2(-250,-200),vec2(-150,-200),vec2(-50,-200)}
pos[0]=vec2(-150,-300)

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

-- 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
            return
            print("touch") --just a test to see if it registers the touch
        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 and clear button
sprite(clearButton, WIDTH/2-250, HEIGHT/2-300, 75)
sprite(backspaceButton, WIDTH/2-50, HEIGHT/2-300, 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

end

I’ve looked up project data and assets. I have pulled in a windmill image with the statement:

sprite(“Small World:Windmill”,_pos._x,pos.y,75)

And looked at moving data into my global project file on post

http://codea.io/talk/discussion/6448/downloading-multiple-images-via-http-request

Where is @CodingIsLife’s project data coming from?

I looked at this post:

http://codea.io/talk/discussion/58/persistent-data

To see that project data is stored in a Data.plist file. When I look up Data.plist I go to an iOS developer page, which is way out of the scope for Codea

The data is stored locally on the iPad, so unless he shares the pictures with you, you’ll have to make your own, or else just print numbers on the screen instead of pictures (see my code for this a little higher up).

Yes I am using my own images. They are straight from either Google or some icon website. I’d be happy to share the images if it allows other people to use the program I’m making :slight_smile:

@CodingIslife … I used the wrong Google search the first time I looked for buttons. Found a link to a site http://dabuttonfactory.com/ which should help me experiment with buttons. I will need to do this and will use your program as a template.

I think you have reached a difficult part in your development and recommend that you read http://codeatuts.blogspot.com.au/2012/07/tutorial-5-finite-state-machines.html before attempting the buttons on your own. The user experience for your program is going to be initially a little frustrating for negative numbers I suspect. I am looking forward to seeing your code for presenting answers for addition problems!

@ignatz I have been messing with Codea for a couple of months now and am finally getting a feel for the language. Text and Sprite both use the center of the displayed object making your obj vec2(touch.x,touch.y) … obj:dist(object location) … Coding pattern really cool. I’ve been messing with my own button logic that I drew from the lower left corner, making handling the touch event a lot more complicated. I really appreciate the work you have done with Codea. I hope to be able to discuss graphics with you a little more intelligently real soon now :-bd

@CodingIsLife Here’s a keyboard that I had that uses built in emoji images, so anyone can use it. It handles BACKSPACE (single triangle), CLEAR (double triangle), ENTER (curly arrow). The * and # buttons do nothing in this example.

function setup()
    pic={"*??","??","#??","??","0??","?","1??","2??",
            "3??","4??","5??","6??","7??","8??","9??"}
    val={-99,-4,-99,-1,0,-2,1,2,3,4,5,6,7,8,9}
    rectMode(CENTER)
    butt={}
    count=0
    for y=1,5 do
        for x=1,3 do
            count=count+1
            table.insert(butt,button(100+x*70,200+y*70,70,count))
        end
    end
    value=0
end

function draw()
    background(40, 40, 50)    
    stroke(206, 223, 228, 255)
    strokeWidth(5)
    fill(0, 176, 255, 255)
    rect(240,410,220,360)
    for a,b in pairs(butt) do
        b:draw()
    end
    fill(0,176,255,255)
    rect(240,620,220,50)
    fill(255)
    fontSize(40)
    fill(255)
    text(value,240,620)
end

function touched(t)
    for a,b in pairs(butt) do
        b:touched(t,a)
    end
end

button=class()

function button:init(x,y,w,c)
    self.x=x
    self.y=y
    self.w=w
    self.pic=pic[c]
    self.keyVal=val[c]
end

function button:draw()
    fontSize(65)
    fill(255)
    text(self.pic,self.x,self.y)       
end

function button:touched(t,a)
    if t.state==BEGAN then
        if t.x>self.x-self.w/2 and t.x<self.x+self.w/2 and
                t.y>self.y-self.w/2 and t.y<self.y+self.w/2 then
            if self.keyVal>=0 then
                value=value*10+self.keyVal
            elseif self.keyVal==-1 then
                value=value//10
            elseif self.keyVal==-2 then
                value=0
            elseif self.keyVal==-4 then
                print(value)
                value=0
            end
        end
    end
end