Frustrations

@LadyJayne it’s just the name of the variable, it’s a little bit eccentric looking.

More formally, you could write that loop as:

for key,value in pairs(self.houses) do

Where key and value are set to each key and value of the table at each iteration of the loop. Because I did not plan to use the key at all, I named the key variable _ to indicate it was not going to be used (for reasons of style more than anything).

Not wishing to be picky with the code But… :slight_smile:

I just had a look at the demo (the results look beautiful by the way) and I was wondering in the gradient function the whole inner loop of the step across the is redundant as the value of ‘c’ doesn’t change, you could calculate it outside of the loop, also the gradient image is reserved as being a 64x64 image, I understand the reason for the image to be 64 pixels high to get a decent gradient however you could get away with an image that was potentially 2 or 4 pixels wide (depending on hardware rendering limitations) and be more efficient with memory and texture space.

Still a lovely demo and a great opportunity to learn from.

Respect! :slight_smile:

@TechDojo you’re right, I should have computed c per row, not per pixel. Thanks for pointing that out.

I kept the image square due to the filtering that happens at the edges when you stretch a small texture and smooth() is enabled. It would have created larger stretching artifacts at the sides the thinner the image.

@Simeon Out of interest, is there a particular reason you didn’t use a mesh to draw that gradient?

@frosty a very good reason: I didn’t think of it.

Evening all - How would the gradient be generated via a mesh?

Alright. I’m just not getting this to work. I’m trying to fill a table with 50 instances of the same house at random locations. Then I want to draw all of them on the screen. If anyone could help me out, I would appreciate it. Thanks.


Main

-- Use this function to perform your initial setup
function setup()
    print("Location, Location, Location!")
    
end

-- This function gets called once every frame
function draw()
    -- This sets a dark background color 
    background(40, 40, 50)

    -- This sets the line thickness
    strokeWidth(5)

    -- Do your drawing here

    pushMatrix()

    for _,v in pairs(House.houses)do
        v:draw()
    end  

    popMatrix()
        
end



House = class()
   houses = {}

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

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

    x = math.random(25,560)
    y = math.random(25,450)
    
    h = sprite("Small World:House",x,y)
    
    while #houses < 50 do
        table.insert(houses,h)
        
    end   
end

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

I tried to make your code work, there were a couple of issues.

  • the # does not work on tables properly, you better use table.getn
  • you cannot store a sprite. The sprite function just draws a sprite on the screen afaik.
  • the draw function is not the place to initialize your table as it will be called as often as Codea is able to.
  • houses was not in the scope of House, so it could not be reached by House.houses
-- Use this function to perform your initial setup
function setup()
    print("Location, Location, Location!")
    house = House()
end

-- This function gets called once every frame
function draw()
    -- This sets a dark background color 
    background(40, 40, 50)

    -- This sets the line thickness
    strokeWidth(5)

    -- Do your drawing here

    house:draw()
        
end



House = class()
   

function House:init(x)
    -- you can accept and set parameters here
    self.houses = {}
    
    while table.getn(self.houses) < 50 do
        x = math.random(25,560)
        y = math.random(25,450)
        table.insert(self.houses,vec2(x,y))
    end   
        m
end

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

    for _,v in pairs(self.houses)do
        sprite("Small World:House",v.x,v.y)
    end  

end

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

@LadyJayne Here’s my suggestion of how I’d do this. I’ve tried to add a lot of comments to explain what’s happening where:

-- Use this function to perform your initial setup
function setup()
    print("Location, Location, Location!")   
    
    houses = {}    -- an empty table to store our houses
    
    -- first of all, we'll create 50 House objects and store them in our table
    for i = 1,50 do
        local h = House()    -- create a house
        table.insert(houses, h)    -- add it to the houses table
    end   
    
    -- let's just check how many houses we have
    print("There are " .. #houses .. " houses")
end

-- This function gets called once every frame
function draw()
    -- This sets a dark background color 
    background(40, 40, 50)

    -- now we take each house in turn and tell it to draw itself to the screen
    for _,v in pairs(houses)do
        v:draw()
    end  
end

-- our House class
House = class()
   
function House:init()
    -- each time we create a new house (by calling House()), this method
    -- will set the x and y of that new house to random values
    self.x = math.random(25,560)
    self.y = math.random(25,450)
end

function House:draw()
    -- for a house to draw itself, it simply draws the house sprite at the right location
    sprite("Small World:House", self.x, self.y)
end

One of the main differences is that instead of trying to store the actual image of each house in a table, you store a simple house object that knows 3 things: its x position, its y position, and how to draw itself, using its draw method. Each house’s draw method says ‘draw the house sprite at my x and y position’.

Some ideas for small steps to try next:

  • At the moment the houses are all clustered together in the bottom left of the screen. Try seeing if you can spread them out so they’re created across the entire screen. Hint: WIDTH and HEIGHT are built-in variables that represent the size of the screen.
  • Try modifying the code so that each house also has a little tree next to it. Hint: You can do this with just an addition to the House class’s draw() method.

@simeon, love the gradient, sad it’s image:set and loops - they’re not fast. Native Gradients would be really handy.

Actually… I’ll bet we could get an approximation of that by coloring a mesh. Probably not appropriate for this thread :slight_smile:

@Bortels as @frosty mentioned, I could have easily done it with a mesh — just didn’t think of it.

Thank you Doffer and frosty! That helps a lot. I will continue my journey with the next little steps.

Thanks @Simeon, it’s beautiful! I’ve added a bunch of blinking stars and a moon.

In the setup function I’ve added:

    starsTable = {}
    for i=1,200 do
        starsTable[i]=vec2(math.random(0,WIDTH),  math.random(200,HEIGHT),2)
    end

and in the draw function:

    -- Draw the stars
    for i=1,200 do
        fill(math.random(170,255))
        ellipse(starsTable[i].x,starsTable[i].y,2)
    end
    
    -- Draw the moon
    fill(255)
    ellipse(WIDTH-100,HEIGHT-100,100)

I’ve also used a 1x10 pixel image for the gradient with no visible artifacts.

@pepinganos can you post a screenshot? I’m keen to see it :slight_smile:

@frosty is there a built-in ‘isEmpty’ function to check to make sure a space is empty before drawing another object there? With the houses project, they overlap (I understand that it comes from the random coordinates). Also, is the x,y origin of a sprite (or any object for that matter) 0,0 – meaning the lower left corner?

@LadyJayne the x,y coordinate of the sprite refers to the center of the sprite by default. You can change this using the spriteMode function.

spriteMode(CENTER) – The default, the x,y position of the sprite is its center

spriteMode(CORNER) – The x,y position of the sprite is its lower left corner

spriteMode(CORNERS) – The x,y position is the lower left corner, the width and height are instead treated as the upper right corner. Sprite is stretched to fit between the two points.

Great. Thanks. I have now finished the mini-projects that Simeon suggested. The 50 houses took some time. Doffer’s code was a great learning example.

Instead of reposting the code for the 50 houses, I did the following for the blue sky, grass, and tree with each house ( as suggested by Doffer):

In Main(), I drew the background blue. Then I drew a smaller rectangle (width of the screen) and filled it in green. In the House() class, draw() function, I just added a tree sprite before the house sprite, and used the same x,y coordinates used for the house --offsetting them slightly.

I keep telling myself to keep it simple. More practice with this type of coding to get it ingrained, then I will venture on to bigger and better things. Appreciate all the help!

That sounds like a good way to do it.

Glad that you were able to accomplish your project. Simple ideas are the best.

I hope that your frustrations have been replaced with some fun while coding in Codea :smiley:

Nothing special, @Simeon, just a little nuance to your great code.