Help me make my code better

Hey I’m back again, not sure whether this should be posted here or in questions.

Anyhow, I was wondering if I could get some help for my code. I wanted to create a board with actual cases (not just background decoration). I would like to move the characters case by case (succeeded in my previous version) but would like that they can’t go in it if the case is occupied. Also wondering how I could make it so the state (etat) changes when a character is inside it, I thought of making “if” loops but figured it is the same problem that I just stated, I need to figure out how to detect if a sprite is inside it.

PS: sorry if the code/outcome is messy, it was prettier in my previous version but it also wasn’t coded the same way (cases drawn in a class instead of main etc). Hope you dont mind the french in the code as well but I can clear things up if needed thanks alot

you didn’t post the GameLogic class

One thing you can do to make your classes neater, is to use inheritance, to share code between all the classes

We define a base class with all the shared code. Then any class that wants to share that code “inherits” it, as shown below.

--create functions that will be shared by several classes
baseClass = class()

function baseClass:touched(touch)
    if vec2(self.x,self.y):dist(vec2(touch.x,touch.y)) < 50 then 
        self.x=touch.x
        self.y=touch.y   
    end
    --etc all the rest of the shared touched code
end

--same for draw, note we need a variable self.sprite
function baseClass:draw()
    spriteMode(CORNER)
    sprite(self.sprite,self.x+3,self.y+25,100,100)
end

--now create your different classes. If you want to change the
--standard code above, simply replace the function

Colon = class(baseClass) --inherits baseClass code

function Colon:init(i,j,id)
   self.i = i-500
   self.j=j-500
   self.x=cote*self.i
   self.y=cote*self.j
   self.id=id
   self.sprite="Planet Cute:Character Princess Girl" --NOTE THIS
end

--you don't need a Colon touched or draw function because they are
--the same as the base class


Case = class() --Case doesn't use any standard code so DON'T inherit

--all your Case functions are unchanged, same as before


Exploreur = class(baseClass) --inherit  baseClass functions

function Exploreur:init(i,j,id)
   self.i = i
   self.j=j
   self.x=cote*self.i
   self.y=cote*self.j
   self.id=id
   self.sprite="Planet Cute:Character Princess Girl" --NOTE THIS
end

--no need for draw or touched function, they are same as baseClass

--if you wanted to change (say) the draw function for this class, just
--rewrite it
function Exploreur:draw()
    --whatever code you want (replaces baseClass code)
end

--you do need this extra function
function Exploreur:cdde(p)
    q=math.random()
    if q<p then
        self.ph=self.ph
        else
        self.ph=math.random(1,2)
    end
    exploreur = class()      
end

--Guerrier class is similar

@Kostia - we’ll have a look at it - but you forgot to post the code! :stuck_out_tongue:

http://pasted.co/0d1e88c6 Im a dumb dumb

Generally, if you have a board with characters in some of the places, you should use a table to tell you what is in each place.

Then each time you draw, you can loop through all the items in the table, to find out what is in each place.

Yea I skipped the gamelogic because I ended up either putting everything inside Main or Case^^ Where did you see I had a Gamelogic class ?

And thank you very much for the clearing up classes part! But if I understand, say I want to make an exception in one of the classes that use the baseclass. I can keep baseclass in this class but just put a different draw/touch function and it will ‘‘overwrite’’ the baseclass’ priority ?

btw Colon = Settler in english, I’m not into intestines dont worry :tongue:

Mhmm I modified my code and I now have the ''attempt to call method ‘draw’ (a nil value), which is my main and right after ‘‘for i,objet in ipairs(guerriers) do
objet:touched(CurrentTouch)
objet:draw()’’

Any guesses^^?

@Kostia I didn’t look at all of your code to try and figure out everything you were trying to do, but here’s some code I have that might be similar to what you describe at the top. You can move each Sprite around the board, but you can’t move to a square already occupied. There are 3 characters, but more can be added. Also the number of each character can be changed if needed.

PS. If you can’t use this, maybe someone else can think of something to use this for. I don’t have a use for it, I just wrote it for something to do.

EDIT: Code removed to save space. See code farther down. Removed // and replaced with math.floor.

@Kostia - yes, to overwrite a function from the base class, you just put in a function in the child class (try it with a little test project, I suggest).

I don’t know where the problem is, without seeing your code.

And you will find the GameLogic error if you run the code you posted at the top.

Hi @dave1707 thanks for the code it tried it on it’s own but I have Errors from the double slashes // and when removjng them I get an error line 53

Attempt to index field ´?´ a nil value :tongue:

And thanks @Ignatz I will have a look with my teacher tommorow :slight_smile:

What version of Codea are you using? The double slashes are a Lua 5.3 feature. Codea switched from Lua 5.2 to 5.3 last March, with version 2.3

@Kostia Here’s a version that doesn’t use the // . You should update your version of Codea.

supportedOrientations(PORTRAIT_ANY)
displayMode(FULLSCREEN)

function setup()
    spr={"Planet Cute:Character Pink Girl",
        "Planet Cute:Character Horn Girl",
        "Planet Cute:Character Cat Girl"}
    selected=0
    tab={}
    for x=1,13 do       
        tab[x]={}
        for y=1,19 do
            v=math.random(8)
            if v>3 then
                v=0
            end
            tab[x][y]=v
        end
    end
    size=50
end

function draw()
    background(40, 40, 50)
    stroke(255)
    strokeWidth(2)
    for x=1,13 do
        for y=1,19 do
            rect(x*size,y*size,size,size)
            s=tab[x][y]
            if s>0 then
                sprite(spr[s],x*size+25,y*size+35,50)
            end
        end
    end
    if selected>0 then
        sprite(spr[selected],tx,ty,50)
    end
end

function touched(t)
    x=math.floor(t.x/size)
    y=math.floor(t.y/size)
    if x<1 or x>13 or y<1 or y>19 then
        if selected>0 then
            set()
        end
        return
    end
    if t.state==BEGAN then
        tx,ty=t.x,t.y
        if tab[x][y]>0 then
            selected=tab[x][y]
            tab[x][y]=0
        else
            return
        end
    end
    if t.state==MOVING and selected>0 then
        if tab[x][y]==0 then
            tx,ty=t.x,t.y
        else
            set()
        end
    end
    if t.state==ENDED and selected>0 then
        set()
    end
end

function set()
    x=math.floor(tx/size)
    y=math.floor(ty/size)
    tab[x][y]=selected
    selected=0
end

Thank you everyone, but im kind of afraid to update the app though as it may cause bugs, no?

Anyway, I got this done today, tell me what you think and what I should improve ^^ (I did find a couple of bugs myself but I don’t know if it’s worth fixing them haha)


--# Main
-- Isn2.4
Case = class()

function Case:init(i,j,etat)
    -- you can accept and set parameters here
    self.i = i
    self.j = j
    self.etat = etat
    couleurs={color(255),color(255,0,0,255),color(9, 255, 0, 255),color(238, 0, 255, 255)}
end

function Case:draw()
    strokeWidth(6)
    stroke(couleurs[self.etat])
    fill(0)
    rect(cotedam*self.i,cotedam*self.j,cotedam,cotedam)
    
end

function Case:touched(touch)
    -- Codea does not automatically call this method
end

Colon = class()

function Colon:init(i,j,id)
    -- you can accept and set parameters here
    self.i = i
    self.j=j
    self.x=cote*self.i
    self.y=cote*self.j
    self.id=id
    self.i0=self.i
    self.j0=self.j
end
function Colon:draw()
    spriteMode(CORNER)
    sprite("Planet Cute:Character Princess Girl",self.x+3,self.y+25,100,100)
    
end

function Colon:touched(touch)
    if vec2(self.x,self.y):dist(vec2(touch.x,touch.y)) < 50 then
        self.x=touch.x
        self.y=touch.y
    end
    if touch.state==BEGAN or touch.state==MOVING then
        if (touch.x>cotedam*self.i and touch.x<cotedam*(self.i+1)) and (touch.y>cotedam*self.j and touch.y<cotedam*(self.j+1))  then
            self.x=touch.x-cote/2
            self.y=touch.y-cote/2
        end
    elseif touch.state==ENDED then
        if (touch.x>cotedam*(self.i-1) and touch.x<cotedam*(self.i+2)) and (touch.y>cotedam*(self.j-1) and touch.y<cotedam*(self.j+2))  then
            self.i=math.ceil(touch.x/cotedam)-1
            self.j=math.ceil(touch.y/cotedam)-1
            if cases[6*(self.i)+(self.j+1)].etat==1 then
                cases[6*(self.i)+(self.j+1)].etat=4
                if self.i0~=self.i or self.j0~=self.j then
                    cases[6*(self.i0)+(self.j0+1)].etat=1
                    self.i0=self.i
                    self.j0=self.j
                end
            else
                self.i=self.i0
                self.j=self.j0
            end
            
        end
        -- limite du damier
        if self.i<0 then
            self.i=0
        end
        if self.j<0 then
            self.j=0
        end
        if self.i>nb_l then
            self.i=nb_l
        end
        if self.j>nb_h then
            self.j=nb_h
        end
        self.x=cotedam*self.i
        self.y=cotedam*self.j
        
        
        -- Codea does not automatically call this method
    end
end

Exploreur = class()

function Exploreur:init(i,j,id)
    -- you can accept and set parameters here
    self.i = i
    self.j=j
    self.x=cote*self.i
    self.y=cote*self.j
    self.id=id
    self.i0=self.i
    self.j0=self.j
end

function Exploreur:draw()
    
    spriteMode(CORNER)
    sprite("Planet Cute:Character Boy",self.x+3,self.y+25,100,100)
    
end
-- Codea does not automatically call this method
function Exploreur:cdde(p)
    q=math.random()
    if q<p then
        self.ph=self.ph
    else
        self.ph=math.random(1,2)
    end
    exploreur = class()
    
    
end

function Exploreur:touched(touch)
    if vec2(self.x,self.y):dist(vec2(touch.x,touch.y)) < 50 then
        self.x=touch.x
        self.y=touch.y
    end
    if touch.state==BEGAN or touch.state==MOVING then
        if (touch.x>cotedam*self.i and touch.x<cotedam*(self.i+1)) and (touch.y>cotedam*self.j and touch.y<cotedam*(self.j+1))  then
            self.x=touch.x-cote/2
            self.y=touch.y-cote/2
        end
    elseif touch.state==ENDED then
        if (touch.x>cotedam*(self.i-1) and touch.x<cotedam*(self.i+2)) and (touch.y>cotedam*(self.j-1) and touch.y<cotedam*(self.j+2))  then
            self.i=math.ceil(touch.x/cotedam)-1
            self.j=math.ceil(touch.y/cotedam)-1
            if cases[6*(self.i)+(self.j+1)].etat==1 then
                cases[6*(self.i)+(self.j+1)].etat=3
                if self.i0~=self.i or self.j0~=self.j then
                    cases[6*(self.i0) + (self.j0+1)].etat=1
                    self.i0=self.i
                    self.j0=self.j
                end
            else
                self.i=self.i0
                self.j=self.j0
            end
            
        end
        -- limite du damier
        if self.i<0 then
            self.i=0
        end
        if self.j<0 then
            self.j=0
        end
        if self.i>nb_l then
            self.i=nb_l
        end
        if self.j>nb_h then
            self.j=nb_h
        end
        self.x=cotedam*self.i
        self.y=cotedam*self.j
        
        
        -- Codea does not automatically call this method
    end
end

Guerrier = class()

function Guerrier:init(i,j,id)
    -- you can accept and set parameters here
    self.i = i
    self.j=j
    self.x=cotedam*self.i
    self.y=cotedam*self.j
    self.id=id
    self.i0=self.i
    self.j0=self.j
end

function Guerrier:draw()
    spriteMode(CORNER)
    sprite("Planet Cute:Character Horn Girl",self.x+3,self.y+3,100,100)
    
end

function Guerrier:touched(touch)
    if touch.state==BEGAN or touch.state==MOVING then
        if (touch.x>cotedam*self.i and touch.x<cotedam*(self.i+1)) and (touch.y>cotedam*self.j and touch.y<cotedam*(self.j+1))  then
            self.x=touch.x-cote/2
            self.y=touch.y-cote/2
        end
        
    elseif touch.state==ENDED then
        if (touch.x>cotedam*(self.i-1) and touch.x<cotedam*(self.i+2)) and (touch.y>cotedam*(self.j-1) and touch.y<cotedam*(self.j+2))  then
            self.i=math.ceil(touch.x/cotedam)-1
            self.j=math.ceil(touch.y/cotedam)-1
            if cases[6*(self.i)+(self.j+1)].etat==1 then
                cases[6*(self.i)+(self.j+1)].etat=2
                if self.i0~=self.i or self.j0~=self.j then
                    cases[6*(self.i0) + (self.j0+1)].etat=1
                    self.i0=self.i
                    self.j0=self.j
                end
            else
                self.i=self.i0
                self.j=self.j0
            end
            
        end
        -- limite du damier
        if self.i<0 then
            self.i=0
        end
        if self.j<0 then
            self.j=0
        end
        if self.i>nb_l then
            self.i=nb_l
        end
        if self.j>nb_h then
            self.j=nb_h
        end
        self.x=cotedam*self.i
        self.y=cotedam*self.j
        
        
        -- Codea does not automatically call this method
    end
end

-- Civ Isn

-- Use this function to perform your initial setup
function setup()
    llc=100
    cote=50
    cotedam=110
    nb_l=math.ceil(WIDTH/cotedam)-2
    nb_h=math.ceil(HEIGHT/cotedam)-2
    exploreurs={}
    table.insert(exploreurs, Exploreur(1,1))
    guerriers={}
    table.insert(guerriers, Guerrier(5,5))
    colons={}
    table.insert(colons, Colon(1,5))
    cases={}
    for i=0,nb_l do
        for j=0,nb_h do
            table.insert(cases,Case(i,j,1))
        end
    end
    
end

-- This function gets called once every frame
function draw()
    background(1, 1, 1, 255)
    for i,objet in ipairs(cases) do
        objet:draw()
    end
    -- Do your drawing here
    
    for i,objet in ipairs(guerriers) do
        objet:touched(CurrentTouch)
        objet:draw()
    end
    for i,objet in ipairs(exploreurs) do
        objet:touched(CurrentTouch)
        objet:draw()
    end
    for i,objet in ipairs(colons) do
        objet:touched(CurrentTouch)
       -- print(CurrentTouch)
        --if CurrentTouch.state==ENDED then
        --  objet.x=objet.dpx
        --objet.y=objet.dpy
        -- end
        objet:draw()
    end
end

@Kostia When you post code, put 3~'s on a line before and after your code so it formats correctly on the forum. I added them to your code above. I’m not sure what you’re trying to do. It looks like you can move a character around the grid and if you try to move to a square near another character, that character will block your move. That could be the start to an interesting game. Not sure what the colored squares are for though.

@Kostia Updating Codea shouldn’t cause any errors. A lot of people have already done it and if there were errors, they’ve been corrected already. You’ll run into more problems with Codea by not updating than you will have by updating. But then that’s up to you. If you’re comfortable with the version you’re on, that’s fine. You’ll have to learn the differences because most people won’t modify their code so it works for you. You’ll have to learn how to make those changes so they work with your version.