Howdy, Stranger!

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

Making a Level

edited June 2012 Posts: 68

As I'm a wannabe coder I've coded a lot in Game Maker. As ppl know, making a level in Game Maker is entirely visual based.
So my question is, how do I go about placing dirt blocks/walls and stuff in my game? The example game in Codea didn't get through to me.

I'm assuming there's gonna be a lot of "for loops" and stuff so I'm giving everyone permision to talk to me like I'm a child so as to help me understand better

EDIT: whistle whistle still waiting for a reply

Tagged:

• Posts: 18

You could create a separate class for the level and the walls. Have you taken a look at the Dungeon Roller example? That's a relatively straight forward example on how to draw walls around the screen.

• Posts: 68

It didn't seem so straightforward to me @.@
I've looked at it and wound up more confused

• Posts: 19

function World:draw()
-- Codea does not automatically call this method
itemDrawn = false
for y = #self.blocks[1],1,-1 do
for x = 1,#self.blocks do
self.blocks[x][y]:draw()
end
end
Since im not used to LUA syntax, i dont understand for loops yet, but i know he used a for loop on its constructor and draw function(i might be wrong but i think thats pretty much it..)

• edited June 2012 Posts: 68

I'm glad someone responded but I'm afraid I'm even more confused.
doing a number map has something to do with it, right?

``````{0,0,0,0,0,0}
{0,1,1,1,1,0}
{0,1,1,2,1,0}
{0,0,0,0,0,0}

-- 0 = Wall
-- 1 = Grass
-- 2 = Character
``````

or am I waay off base?
how does a for loop work exactly? And how does a for loop make my map above into sprite tiles?
And lastly is this something super basic that I'm not getting? I kinda feel like a retard right now

• Posts: 41

RichGala1...I know what you're talking about. I have programmed with GameMaker, as well. Making the switch to Codea was quite different. I've toyed around with Codea for a month or so now, and I have just learned (and gotten a lot of help from members of the forum!) how to set blocks on the screen in a configuration that I want. I did it with separate classes for level and block (like what ChrisF was referring to). I took from the Brickout example (Dungeon Roller is not self-explanatory to me either). Here is what I've come up with. There may be a better way to do it, but...

``````#level
levels = {

{{0,1,1,1,0},{1,1,0,1,1},{1,0,1,0,1}}

}
``````

--first inside bracket is top row. The numbers are places where the walls will go. 0 = an empty spot. 1 = spot where the wall will be drawn. The outer brackets indicates level 1. In this example, I will have three rows of a possible 5 walls.

``````#wall
wall = class()

function wall:init(x,y)
-- you can accept and set parameters here
self.pos = vec2(x,y)
self.size = vec2(101,171)
end

function wall:draw()
-- Codea does not automatically call this method
sprite("Planet Cute:Stone Block",self.pos.x,self.pos.y)
end

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

--this class is the wall block. self.pos is a vec2 with x, y values that will be identified in the #Main(). self.size is a vec2 with values for the width and height of the sprite being used.

``````#Main

displayMode(FULLSCREEN)
supportedOrientations(CurrentOrientation)

walls = {}
level = 1

function setup()

makeWalls()

end

function makeWalls()
for i = 1, 3 do --rows
for j = 1, 5 do  --columns
if levels[level][i][j] > 0 then
table.insert(walls,wall(200 + (j * 103),HEIGHT - (i*85 + 35)))
end
end
end
end

function draw()

background(27, 27, 218, 255)

for i = 1, table.maxn(walls, i) do
walls[i]:draw()
end

end
``````

--'walls' is a table to hold the wall sprite so they can be drawn on the screen. I don't know why makeWalls() has to be in the setup(), but the code won't work without it there. If you play with the numbers in the table.insert, you'll see how it effects the x or y shift, as well as the spacing between blocks.

I hope this helps. Good luck, and have fun.

• Posts: 68

Thank you so much! Someone who understands the transition
I will try out the code immediately. I've only skimmed it so far and I can already tell that this is EXACTLY what I needed XD

• Posts: 68

I tried your code but it didn't work. Codea says:

``````error: [string "..."]:15: attempt to index field '?' (a nil value)
Pausing playback
error: [string "..."]:31: attempt to call global 'maxn' (a nil value)
Pausing playback
``````

Wasn't sure what "maxn" was supposed to do..

• Posts: 68

turns out I just did something retarded XP
BUT what do I add if I want the "0"'s to be grass tiles and the 1's to be walls?

• Posts: 41

@RichGala1: the table.maxn is telling the loop to go through to the maximum number of instances held in the table.

I'm not sure about the other question: making the 0's a different tile. That may be better done with meshes, but I have not gotten that far. Hopefully someone else on the forum can answer that one for you.

• edited June 2012 Posts: 7

@RichGala1

I think you might also want to take a loom at the 3d lab it has 3 declared meshes in its 2nd example:

``````Test2 = class()

function Test2:name()
return "3D Blocks"
end

function Test2:init()
-- all the unique vertices that make up a cube
local vertices = {
vec3(-0.5, -0.5,  0.5), -- Left  bottom front
vec3( 0.5, -0.5,  0.5), -- Right bottom front
vec3( 0.5,  0.5,  0.5), -- Right top    front
vec3(-0.5,  0.5,  0.5), -- Left  top    front
vec3(-0.5, -0.5, -0.5), -- Left  bottom back
vec3( 0.5, -0.5, -0.5), -- Right bottom back
vec3( 0.5,  0.5, -0.5), -- Right top    back
vec3(-0.5,  0.5, -0.5), -- Left  top    back
}

-- now construct a cube out of the vertices above
local cubeverts = {
-- Front
vertices[1], vertices[2], vertices[3],
vertices[1], vertices[3], vertices[4],
-- Right
vertices[2], vertices[6], vertices[7],
vertices[2], vertices[7], vertices[3],
-- Back
vertices[6], vertices[5], vertices[8],
vertices[6], vertices[8], vertices[7],
-- Left
vertices[5], vertices[1], vertices[4],
vertices[5], vertices[4], vertices[8],
-- Top
vertices[4], vertices[3], vertices[7],
vertices[4], vertices[7], vertices[8],
-- Bottom
vertices[5], vertices[6], vertices[2],
vertices[5], vertices[2], vertices[1],
}

-- all the unique texture positions needed
local texvertices = { vec2(0.03,0.24),
vec2(0.97,0.24),
vec2(0.03,0.69),
vec2(0.97,0.69) }

-- apply the texture coordinates to each triangle
local cubetexCoords = {
-- Front
texvertices[1], texvertices[2], texvertices[4],
texvertices[1], texvertices[4], texvertices[3],
-- Right
texvertices[1], texvertices[2], texvertices[4],
texvertices[1], texvertices[4], texvertices[3],
-- Back
texvertices[1], texvertices[2], texvertices[4],
texvertices[1], texvertices[4], texvertices[3],
-- Left
texvertices[1], texvertices[2], texvertices[4],
texvertices[1], texvertices[4], texvertices[3],
-- Top
texvertices[1], texvertices[2], texvertices[4],
texvertices[1], texvertices[4], texvertices[3],
-- Bottom
texvertices[1], texvertices[2], texvertices[4],
texvertices[1], texvertices[4], texvertices[3],
}

-- now we make our 3 different block types
self.ms = mesh()
self.ms.vertices = cubeverts
self.ms.texture = "Planet Cute:Stone Block"
self.ms.texCoords = cubetexCoords
self.ms:setColors(255,255,255,255)

self.md = mesh()
self.md.vertices = cubeverts
self.md.texture = "Planet Cute:Dirt Block"
self.md.texCoords = cubetexCoords
self.md:setColors(255,255,255,255)

self.mg = mesh()
self.mg.vertices = cubeverts
self.mg.texture = "Planet Cute:Grass Block"
self.mg.texCoords = cubetexCoords
self.mg:setColors(255,255,255,255)

-- currently doesnt work properly without backfaces
self.mw = mesh()
self.mw.vertices = cubeverts
self.mw.texture = "Planet Cute:Water Block"
self.mw.texCoords = cubetexCoords
self.mw:setColors(255,255,255,100)

-- stick 'em in a table
self.blocks = { self.mg, self.md, self.ms }

-- our scene itself
-- numbers correspond to block positions in the blockTypes table
--             bottom      middle      top
self.scene = {   { {3, 3, 0}, {2, 0, 0}, {0, 0, 0} },
{ {3, 3, 3}, {2, 2, 0}, {1, 0, 0} },
{ {3, 3, 3}, {2, 2, 2}, {1, 1, 0} } }
end

function Test2:draw()
pushMatrix()
pushStyle()

-- Make a floor
translate(0,-Size/2,0)
rotate(Angle,0,1,0)
rotate(90,1,0,0)
sprite("SpaceCute:Background", 0, 0, 300, 300)

-- render each block in turn
for zi,zv in ipairs(self.scene) do
for yi,yv in ipairs(zv) do
for xi, xv in ipairs(yv) do
-- apply each transform  need - rotate, scale, translate to the correct place
resetMatrix()
rotate(Angle,0,1,0)

local s = Size*0.25
scale(s,s,s)

translate(xi-2, yi-2, zi-2)    -- renders based on corner
-- so -2 fudges it near center

if xv > 0 then
self.blocks[xv]:draw()
end
end
end
end

popStyle()
popMatrix()
end

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

You can completely ignore the 3d aspects of this I think this part in particular might help:

`````` -- now we make our 3 different block types
self.ms = mesh()
self.ms.vertices = cubeverts
self.ms.texture = "Planet Cute:Stone Block"
self.ms.texCoords = cubetexCoords
self.ms:setColors(255,255,255,255)

self.md = mesh()
self.md.vertices = cubeverts
self.md.texture = "Planet Cute:Dirt Block"
self.md.texCoords = cubetexCoords
self.md:setColors(255,255,255,255)

self.mg = mesh()
self.mg.vertices = cubeverts
self.mg.texture = "Planet Cute:Grass Block"
self.mg.texCoords = cubetexCoords
self.mg:setColors(255,255,255,255)

-- currently doesnt work properly without backfaces
self.mw = mesh()
self.mw.vertices = cubeverts
self.mw.texture = "Planet Cute:Water Block"
self.mw.texCoords = cubetexCoords
self.mw:setColors(255,255,255,100)

-- stick 'em in a table
self.blocks = { self.mg, self.md, self.ms }

-- our scene itself
-- numbers correspond to block positions in the blockTypes table
--             bottom      middle      top
self.scene = {   { {3, 3, 0}, {2, 0, 0}, {0, 0, 0} },
{ {3, 3, 3}, {2, 2, 0}, {1, 0, 0} },
{ {3, 3, 3}, {2, 2, 2}, {1, 1, 0} } }
end
``````

And don't forget you can draw your own sprites with spritely

• Posts: 730

You can change the wall draw function to draw different sprites by passing the value from the level class. The program posted above only draws a sprite if the value is greater than zero. In the example below 1 draws a grass block, 2 draws a stone block. Add more if statements as required.

``````#wall
wall = class()

function wall:init(x,y,i)
-- you can accept and set parameters here
self.pos = vec2(x,y)
self.size = vec2(101,171)
self.i=I
end

function wall:draw()
-- Codea does not automatically call this method
if self.i==1 then
sprite("Planet Cute:Grass Block",self.pos.x,self.pos.y)
end
if self.i==2 then
sprite("Planet Cute:Stone Block",self.pos.x,self.pos.y)
end

end

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

And in main change the table.insert to pass the third variable of the value [j]

``````table.insert(walls,wall(200 + (j * 103),HEIGHT - (i*85 + 35),[j]))
``````
• edited June 2012 Posts: 68

I tried what you suggested, West. But for some reason Codea says there is something wrong with the " [ j ]" variable for the table.insert()

I thought maybe if I removed the "[ ]" but then only 2 columns show up, one column wall the other grass.

but WITH the "[ ]" a red pop-up says: Unexpected symbol near '['

EDIT: I figured it out!!!!

Not gonna lie, I feel AWESOME at the moment. I kinda feel retarded about not understanding but still! :P

btw instead of "[j]" I put:

``````table.insert(walls,wall(200 + (j*103), HEIGHT - (i*85 + 35),levels[level][i][j]
``````

Now I just need to figure out how to keep my character from running into the wall

• Posts: 730

Oops - sorry for the error - didn't test the code before posting. Glad you figured it out ;-)

• Posts: 37

Hi! I've been looking for this information for a while. First, thanks for the help.
I tried running the main, wall, and level class together as described above. All I get is a blue screen. Please help!! @.@

• edited July 2013 Posts: 37

My code below:

• Posts: 37
``````--# Main
-- Main

displayMode(FULLSCREEN)
supportedOrientations(CurrentOrientation)

walls = {}
level = 1

function setup()

makeWalls()

end

function makeWalls()
for i = 1, 3 do --rows
for j = 1, 5 do  --columns
if levels[level][i][j] > 0 then
table.insert(walls, wall(200+(j*103), HEIGHT-(i*85+35), levels[level][i][j]))
end
end
end
end

function draw()

background(27, 27, 218, 255)

for i = 1, table.maxn(walls, i) do
walls[i]:draw()
end

end

--# wall
wall = class()

function wall:init(x,y,i)
-- you can accept and set parameters here
self.pos = vec2(x,y)
self.size = vec2(101,171)
self.i = I
end

function wall:draw()
-- Codea does not automatically call this method
if self.i == 1 then
sprite("Planet Cute:Grass Block", self.pos.x, self.pos.y)
end
if self.i == 2 then
sprite("Planet Cute:Stone Block Tall", self.pos.x, self.pos.y)
end
end

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

--# level

levels = {

{{0,1,1,1,0}, {1,1,0,1,1}, {1,0,1,0,1}}

}

``````
• edited July 2013 Posts: 2,042

@Kempoman, in walls you need to do "self.i = i", not "self.i = I" because variables are case-sensitive. Here is working code:

``````--# Main
-- Level Making
displayMode(FULLSCREEN)
supportedOrientations(CurrentOrientation)

function setup()
walls = {}

levels = {

{{2,1,1,1,3,3,3,1,1,2,1},{1,1,3,1,1,1,2,1,3,2,2},{1,3,1,3,1,1,1,2,1,3,1},            {2,1,1,1,3,3,3,1,1,2,1},{1,1,3,1,1,1,2,1,3,2,2},{1,3,1,3,1,1,1,2,1,3,1},{2,1,1,1,3,3,3,1,1,2,1},{1,1,3,1,1,1,2,1,3,2,2},{2,2,2,2,2,1,1,1,1,1,2}},

{{1,1,2,1,3,2,3,1,2,2,3}, {1,1,3,2,1,3,1,1,3,2,1}, {2,3,2,3,1,3,1,1,1,3,2},{1,1,1,1,3,3,2,1,2,2,1}, {2,1,3,1,3,1,1,1,3,1,2}, {1,3,1,3,1,3,1,2,1,2,1}, {2,3,1,1,2,3,2,1,3,2,1}, {1,2,3,1,3,1,2,1,2,2,2}, {2,3,2,3,2,1,2,1,2,1,2}}

} -- Creates a table of levels with two levels that have 9 rows and 11 collumns, each number 1-3 represents a different tile

level = 1 -- Select the first level

makeWalls() -- Call the function to draw the tiles
end

function makeWalls()
for i = 1, #levels[level] do --rows
for j = 1, #levels[level][i] do  --columns
if j > 0 then -- If the tile type isnt 0 make a tile
table.insert(walls,wall((j * 101 - 50.5),HEIGHT - (i*85 - 50), levels[level][i][j]))
end
end
end
end

function createRandomLevel()
table.insert(levels, level, {}) -- Create a table in our levels table for the new level
for i = 1, 9 do
table.insert(levels[level], {}) -- Create 9 rows
for j = 1,11 do
table.insert(levels[level][i], math.random(1,3)) -- Insert random tile values into the rows
end
end
makeWalls() -- Have it make the blocks for the level we just created
end

function draw()
background(0, 0, 0, 255) -- Set a black background

for i = 1, #walls do -- For every block in the table walls
walls[i]:draw() -- draw the correct sprite
end

fill(255, 0, 0, 255)
rect(WIDTH/2 - 50, HEIGHT-20, 100,20)
fill(255, 255, 255, 255)
text("FPS:"..1/DeltaTime, WIDTH/2, HEIGHT - 10)
end

function touched(touch)
if CurrentTouch.state == ENDED then -- If touch is over then
level = level + 1 -- change level
for i = 1, #walls do
table.remove(walls, i) -- Remove the old blocks from the table
end
if levels[level] == nil then -- If that level doesn't exist then
createRandomLevel() -- Call the function to make a new level
else -- if a level already exists then
makeWalls() -- Have it make the blocks for the next level
end
end
end

--# wall
wall = class()

function wall:init(x,y,i)
-- you can accept and set parameters here
self.pos = vec2(x,y) -- Set the position based on the parameter given
self.size = vec2(101,171) -- Size of the blocks
self.i = i
end

function wall:draw()
-- Codea does not automatically call this method
if self.i == 1 then
sprite("Planet Cute:Grass Block",self.pos.x,self.pos.y,self.size.x,self.size.y) -- Draw the grass block at the correct position and size specified above
end
if self.i == 2 then
sprite("Planet Cute:Stone Block",self.pos.x,self.pos.y,self.size.x,self.size.y) -- Draw the stone block at the correct position and size specified above
end
if self.i == 3 then
sprite("Planet Cute:Dirt Block",self.pos.x,self.pos.y,self.size.x,self.size.y) -- Draw the dirt block at the correct position and size specified above
end

end

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

EDIT: added comments and changed it to tile the whole screen, also added a random level generator

• Posts: 37

@JakAttak Thanks so much!! I can't believe how great the people on this forum are!!! If I ever figure this stuff out I will try to do the same!!

• Mod
Posts: 5,396

@Kempoman - this code can be improved quite a bit. For example, it's probably a good idea to put the sprite names in a table, like so

sprites={"Planet Cute:Grass Block","Planet.....","Planet.....",....}

then in wall:draw(), you just say

sprite(sprites[self.i],self.pos.x,self.pos.y, ..etc)

actually, I wouldn't have a wall class at all, for single blocks. I can see the sense in having a level class, though, because that could manage everything that happens in each level. Also, because you are going to use the same map until you change levels, that class could draw the map on an image, and just sprite that image on each draw, instead of having to draw each block separately.

Anyway, as long as you are having fun...!

• Posts: 37

Wow! Thanks Ignatz!! That is some stellar advice. I will try putting the sprites in a table. I was not sure whether to make my map changeable by the player or not. I think that now I will keep everything as simple as I can while I'm learning and try out the single image level.

• Mod
Posts: 5,396

good idea, start simple, add complexity a bit at a time...

• Posts: 688

This is an interesting thread with a lot of useful info, however (also as a GameMaker user) I do understand the question / point the OP raised.

What would be REALLY cool for Codea would be to include more tools - like the room / level editor in Gamemaker in the labs section or as an example (like Spritely) so people could design 2D levels in a consistent manner and be able to export that data easily to their lua apps.

This would really make Codea rock as a game prototyping tool.

• edited July 2013 Posts: 391

I have been working on a 2D map editor which includes auto-tiling, similar to how programs like RPG Maker generate their 2D grid maps. The project so far will take tile sheets and break them down into the necessary components to make the smooth transitions on the generated map. Basic auto-tiling consists of 13 parts: 4 outer corners, 4 inner corners, 4 edges, and a full tile.

This type of map will most likely be used for RPG type games, but with some imagination it could be adopted to almost any genre. Check out some of the progress in the discussion below.

http://twolivesleft.com/Codea/Talk/discussion/comment/24480

Tilesheet set I have used for debugging:

Character set I used for debugging:

I chose to do auto-tiling similar to RPG Maker since there is an abundance of free tilesheet sets and character sets available in this format.

I have sent the code to Ignatz as of yesterday for some help with documentation so it can be used by anyone with any amount of coding experience. There is no awesome GUI for the creation of the maps, but I did simplify it down to sets of 2D tables which are simply filled with numbers indicating which tile sheet is used. Tile sheets are stored in tables of their own with additional information such as the auto-tiling type (floor, roof/wall, waterfall/animated, and none) and whether or not the player would be allowed to walk on the tile. I have floor, roof/wall, and none types working with very minor graphical issues for certain tiles.

Building and physically seeing your worlds come to life definitely keeps the motivation alive. This is why in my process of building an RPG, I chose to do the map generation first. When building large games, motivation is key.

• edited July 2013 Posts: 37

X

• edited July 2013 Posts: 37

X

• edited July 2013 Posts: 37

X

• edited July 2013 Posts: 391

I have released my code for 2D map generation with auto-tile using sprite sheets. Please check it out here:

http://twolivesleft.com/Codea/Talk/discussion/3058/

My code will keep your character centered on the screen and the map will move when you move your character. Not sure if that's what you were looking for, but the map generation part is still awesome as it reads from a simple 2D (grid) table.

• edited July 2013 Posts: 37

X

• Posts: 391

@kempoman, how come your last four posts now have a single X in them?

• Mod
Posts: 5,396

he likes blowing kisses

• edited July 2013 Posts: 2,042

:P

• Posts: 37

I wanted to delete them. Sorry