Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

textSize() and Touch?

edited January 2017 in Questions Posts: 39

Hello there.

I am currently working on recreating the game "The Battle of Polytopia" (Previously known as Super Tribes) in Codea. At the moment I am working on the menu. Heres what I've got so far:


-- __________
-- | MyVars |
RECT = 1

TouchObjects = {}

-- ________________
-- | Animatables |
-- Text
Text = class()
-- Animatable Text

function Text:init(str, x, y, size)
    self.str = str
    self.x = x
    self.y = y
    self.size = size or false

    self.originalState = {str = self.str, x = self.x, y = self.y, size = self.size}
end

function Text:draw()
    -- If size is not defined, use the size already set.
    if self.size then
        fontSize(self.size)
    end
    text(self.str, self.x, self.y)
end

-- Colour
Colour = class()
-- Animatable colour

function Colour:init(r,g,b,a)
    -- you can accept and set parameters here
    self.r = r
    self.g = g or false
    self.b = b or false
    self.a = a or 255

    if not (g and b) then
        self.g = self.r.g
        self.b = self.r.b
        self.a = self.r.a
        self.r = self.r.r or 255
    end

    self.originalState = {r = self.r, g = self.g, b = self.b, a = self.a}
end

function Colour:draw()
    -- Codea does not automatically call this method
      return color(self.r, self.g, self.b, self.a)
end

-- roundRect and animatable (taken from Sound Example)
function roundRect(x,y,w,h,r)
    pushStyle()

    insetPos = vec2(x+r,y+r)
    insetSize = vec2(w-2*r,h-2*r)

    --Copy fill into stroke
    local red,green,blue,a = fill()
    stroke(red,green,blue,a)

    noSmooth()
    rectMode(CORNER)
    rect(insetPos.x,insetPos.y,insetSize.x,insetSize.y)

    if r > 0 then
        smooth()
        lineCapMode(ROUND)
        strokeWidth(r*2)

        line(insetPos.x, insetPos.y, 
             insetPos.x + insetSize.x, insetPos.y)
        line(insetPos.x, insetPos.y,
             insetPos.x, insetPos.y + insetSize.y)
        line(insetPos.x, insetPos.y + insetSize.y,
             insetPos.x + insetSize.x, insetPos.y + insetSize.y)
        line(insetPos.x + insetSize.x, insetPos.y,
             insetPos.x + insetSize.x, insetPos.y + insetSize.y)            
    end
    popStyle()
end

RoundRect = class()

function RoundRect:init(x,y,w,h,r)
    self.x = x
    self.y = y
    self.w = w
    self.h = h
    self.r = r

    self.originalState = {x = self.x, y = self.y, w = self.w, h = self.h, r = self.r}
end

function RoundRect:draw()
    roundRect(self.x, self.y, self.w, self.h, self.r)
end

-- ________
-- | Main |

-- Use this function to perform your initial setup
function setup()
    -- Scenes
    menu = Menu()

    -- Set current scene to menu
    setScene(menu)
end

function setScene(s)
    scene = s

    -- Setup the current scene
    scene:setup()
end

-- This function gets called once every frame
function draw()
    -- Call draw function for current scene
    scene:draw()
end

function touched(touch)
    scene:touched(touch)
    Touch:touched(vec2(touch.x, touch.y))
end

-- _________
-- | Menu |

Menu = class()

function Menu:init()
    -- you can accept and set parameters here
end

function Menu:setup()
    -- Colours for opening colour sequence
    bg = Colour(235, 69, 217, 255)
    t1 = tween(1, bg, {r = 241, g = 233, b = 45})
    t2 = tween(1, bg, {r = 0, g = 184, b = 255})

    -- Animatable text
    title = Text("POLY\n TOPIA", WIDTH/2, HEIGHT+100, 90)
    t3 = tween(0.6, title, {y = HEIGHT-230})
    t4 = tween(0.4, title, {y = HEIGHT-270, size = 111})

    tween.sequence(t1, t2, t3, t4)
    t1, t2, t3, t4 = nil

    -- Button Animation
    start = Button("Start", RECT, 12, WIDTH/2, 150, 100, 11)
end

function Menu:draw()
    -- Set the background colour
    background(bg:draw())

    -- Title text
    font("GillSans-Light")
    textAlign(CENTER)
    textMode(CENTER)
    fill(255, 255, 255, 255)
    title:draw()
    start:draw()
end

function Menu:touched(touch)

end

-- _________
-- | Touch |

-- Problem #1: start:touched() not being triggered

-- Trigger the touch function of an object only if that object is touched
Touch = class()

function Touch:init(object)
    table.insert(TouchObjects, object)
end

function Touch:draw()
    -- Codea does not automatically call this method
end

function Touch:touched(p)
    -- Check if the touch is inside any of the objects
    for i,object in pairs(TouchObjects) do
        local l = object.pos.x - object.size.x/2
        local r = object.pos.x + object.size.x/2
        local t = object.pos.y + object.size.y/2
        local b = object.pos.y - object.size.y/2
        if p.x > l and p.x < r and
            p.y > b and p.y < t then
            object:touched()
        end
    end
end


-- __________
-- | Button |

-- Problem #2: [Solved] What's wrong with textSize()?

Button = class()

function Button:init(str,t,s,x,y,r)
    -- you can accept and set parameters here
    self.displayText = str
    self.form = t
    self.x = x
    self.y = y
    self.w = w
    self.r = r or 0
    if s then
        self.s = s
    else
        self.s = fontSize()
    end

    -- Create a custom button to fit the text.
    fontSize(self.s)
    self.text = {}
    self.text.w,self.text.h = textSize(self.displayText)
    print(self.text.w.." "..self.text.h)
    self.w = self.text.w*1.5
    self.h = self.text.h*1.5
    print(self.w)i
    print(self.h)

    -- For Touch()
    self.pos = vec2(0,0)
    self.size = vec2(0,0)

    -- Save original state
    self.originalState = {str = self.str, form = self.form, s = self.s, x = self.x, y = self.y, r = self.r, w = self.w, h = self.h}

    -- Save button to Touch()
    Touch(self)
end

function Button:draw()
    -- Codea does not automatically call this method
    if self.form == RECT then
        fill(255, 0, 196, 255)
        roundRect(self.x-self.w/2, self.y-self.h/2, self.w, self.h, self.r)
        fill(255, 255, 255, 255)
        textAlign(CENTER)
        textMode(CENTER)
        fontSize(self.s)
        text(self.displayText, self.x, self.y)
    end
end

function Button:touched(touch)
    -- Codea does not automatically call this method
    print("Bumbo")
end


I am facing two problems:
One, if you run the code you'll notice the immense size of the start button. This button was supposed to automatically fit the text perfectly using the textSize() function. If someone could explain to me what is going wrong and how to fix it (even if it a stupidly obvious mistake, which I can assure you is very likely).

Two, you may have noticed my Touch() function. The way this is supposed to work is when creating an object (e.g. A button) you run Touch(self), which adds the object to an table. Every time Codea senses a touch, the function cycles through all the objects within the table and checks if the touch is inside any of these, and then calls the touched() function for that specific objects. In the code above it calls start:touched().

Thank you for taking the time to read this through.
Toodles.

EDIT: Problem #1 solved thanks to @dave1707

Comments

  • dave1707dave1707 Mod
    Posts: 7,470

    In your code where you have start=Button(...) you're passing 7 parameters but the function only accepts 6, so the size of r is 100. Don't have time to look at the other problem now.

  • dave1707dave1707 Mod
    Posts: 7,470

    I'm not sure what you're trying to do with the touched class. Are you trying to setup stuff for touch when you create a button.

  • dave1707dave1707 Mod
    Posts: 7,470

    @jaj_TheDeveloper Is this what your trying to do when you create a button. In the code below, you define the button in setup and it creates a round rect button a little larger than the text. The button:touched function checks if a button is touched.

    function setup()
        rectMode(CENTER)
        bTab={}
        table.insert(bTab,button(200,HEIGHT-100,"Menu"))
        table.insert(bTab,button(200,HEIGHT-200,"Start"))
        table.insert(bTab,button(200,HEIGHT-300,"Stop"))
        table.insert(bTab,button(200,HEIGHT-400,"Run"))    
        table.insert(bTab,button(200,HEIGHT-500,"Whatever you want."))    
    end
    
    function draw()
        background(0)
        for a,b in pairs(bTab) do
            b:draw()
        end    
    end
    
    function touched(t)
        for a,b in pairs(bTab) do
            b:touched(t)
        end
    end
    
    button=class()
    
    function button:init(x,y,t)
        self.x=x    -- x pos
        self.y=y    -- y pos
        self.t=t    -- text
        self.sel=false  -- selected
        self.w,self.h=textSize(t)
        self.h=self.h*1.5
    end
    
    function button:draw()
        stroke(0, 217, 255, 255)
        if self.sel then
            stroke(252, 255, 0, 255)
        end
        strokeWidth(self.h)
        line(self.x-self.w/2,self.y,self.x+self.w/2,self.y)
        fill(255,0,0)
        text(self.t,self.x,self.y)
    end
    
    function button:touched(t)
        if t.state==BEGAN then
            self.sel=false
            if t.x>self.x-self.w/2-self.h/2 and t.x<self.x+self.w/2+self.h/2 and
                    t.y>self.y-self.h/2 and t.y<self.y+self.h/2 then
                self.sel=true
            end
        end
    end
    
  • @dave1707 Thanks, my btn problem is now solved. In regards to the to Touch, I would prefer to have a function that checks if the touch is in any objects, such as Units or squares of landthat will call the touched() function for the corresponding object and that object alone. You know the saying, "Never type the same code twice."

Sign In or Register to comment.