#### Howdy, Stranger!

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

# vec2 for terrain.

edited August 2013 Posts: 577

Hi again guys! I have been trying to make 2d terrain for my game, made out of vec2s and sprites, it seems as if I'm doing something wrong though.
Code:

``````-- Char

function setup()
print("Hello World!")
char = vec2(100,200)
charW = 10
charH = 75
touchx = 0
hurt = false
blocks1 = {}
x = 20
for i=1, 60 do
table.insert(blocks1, vec2(x, math.random(1, 13)))
x = x + 20
jump = false
fall = true
end

end

function draw()
if fall == true then
char.y = char.y - 1
end
background(19, 19, 19, 255)
xChar:draw()

-- WIP code for character
if touchx > char.x then
char.x = char.x + 1
charW = -10*3
end

if touchx < char.x then
char.x = char.x - 1
charW = 10*3
end
-- This sets the line thickness
strokeWidth(5)
--for b=1, #blocks1 do
--tint(47, 36, 30, 255)
--sprite("Documents:Star", blocks1[b].x, blocks1[b].y, 20, 200)

--end
for i, v in ipairs(blocks1) do

v.y = blocks1[i].y
v.x = blocks1[i].x

sprite("Documents:Star", blocks1[i].x, blocks1[i].y, 20, 200)

if --math.abs(blocks1[i].x - char.x)<charH/2 --and
math.abs(v.y - char.y)< charH/2
then fall = false
else
fall = true
end

end

end

function touched(touch)
touchx = touch.x

end
``````
Tagged:

• edited August 2013 Posts: 5,396

@Prynok - please put the first three ~ on a separate line, the formatting is messed up

Please also tell us what the problem is

• Posts: 577

Sorry, the problem is that the character still just falls through the terrain.

``````  -- Char

function setup() print("Hello World!") char = vec2(100,200) charW = 10 charH = 75 touchx = 0 hurt = false blocks1 = {} x = 20 for i=1, 60 do table.insert(blocks1, vec2(x, math.random(1, 13))) x = x + 20 jump = false fall = true end

end

function draw() if fall == true then char.y = char.y - 1 end background(19, 19, 19, 255) xChar:draw()

-- WIP code for character if touchx > char.x then char.x = char.x + 1 charW = -10*3 end

if touchx < char.x then char.x = char.x - 1 charW = 10*3 end
-- This sets the line thickness strokeWidth(5) --for b=1, #blocks1 do --tint(47, 36, 30, 255) --sprite("Documents:Star", blocks1[b].x, blocks1[b].y, 20, 200)

--end
for i, v in ipairs(blocks1) do

v.y = blocks1[i].y
v.x = blocks1[i].x

sprite("Documents:Star", blocks1[i].x, blocks1[i].y, 20, 200)

if --math.abs(blocks1[i].x - char.x)<charH/2 --and
math.abs(v.y - char.y)< charH/2
then fall = false else fall = true end

end
end

function touched(touch) touchx = touch.x

end
``````
• Posts: 577

Is this possible? Or should I try a different method.

• Posts: 666

I think that if statement you have is goofy.

First off, if you are going to remove the commented stuff, remove it from this post.

Second, you seem to be comparing the position of the ground minus the character position and seeing if the result is less that half the character height. Personally, I'd do that math on a separate line and I'd actually split it into two, then compare the results, easier to debug.

What I don't understand is why you are checking half the char's height - it look like you have blocks at cords with no height, so why does the character need height for the check?

• Posts: 157

Yeah, this whole piece seems dodgy...

``````if --math.abs(blocks1[i].x - char.x)<charH/2 --and
math.abs(v.y - char.y)< charH/2
then fall = false else fall = true end
``````

first, (v.y-char.y) is backward. Codea places the origin (0,0) at the bottom-left corner of the screen. So when char is above the ground, the y value will always be greater than the ground height.

second, it makes more sense to compare your character's altitude against the ground height. The comparison you're doing there doesn't make any sense until the reader rips it apart and use some algebra to figure out what you're actually trying to do.

``````if (char.y+charH/2) > v.y) then
fall=true
else
fall=false
end

``````

As rule, I never use an if/then statement when all you're doing is setting a Boolean value true or false. Instead, just assign the comparison directly to the Boolean.

``````fall = (char.y+charH/2) > v.y

``````

Finally, you could consider changing your sprite drawing to use CORNER. That simplifies your routine even more, since the x,y positions specified in the Sprite function indicate the lower-left corner of the sprite, not the center.

``````-- at the top of draw()
rectMode(CORNER)

-- in  your collision testing loop
fall=char.y > v.y

``````
• Posts: 577

Yeah, I guess I was a bit to tired when I was making this code, but it still doesn't work. I think the problem is it doesn't know what block is under the character, is that possible?

• edited August 2013 Posts: 157

That's your job as a programmer. You have to determine whether the space you're about to move your character to is already occupied. Then you have to decide what to do when you get there.

The simplest possible method would be a world set up in a square grid, like a chess board. You just test the squares your character could be touching after the next movement cycle...

It's up to you to decide which blocks are close enough to touch. The usual way is to arrange your blocks in a grid, then store the grid in an array (lua calls them "tables".)

The simplest way to store your world in a packed array.

To create your initial map, you create a table with width*height elements and set each element to an "air" block, so that something gets drawn on the screen in that space. The bottom row gets set to "solid" blocks.

``````function createMap(cols,rows,airBlock,solidBlock)
map = {}  -- map is a global
mapRows=rows
mapCols=cols

local x
local y
for x=1,mapRows do
for y=1,mapCols do
if y == 1 then
map[x*mapRows+y]=solidBlock
else
map[x*mapRows+y]=airBlock
end
end
end
end
``````

to find a spot on the grid, you do this:

``````gridX=math.floor(char.x/gridSize)
gridY=math.floor(char.y/gridSize)
``````

to get an individual block from your map, you can use the maths. calling getBlock(48,12) would return the block in column 2, row 1

``````function getBlock(x,y)
gridX=math.floor(char.x/gridSize)
gridY=math.floor(char.y/gridSize)

return map[gridX*mapCols+y]
end function
``````

so to find out if the cell below your character is occupied with a solidBlock, do this:

``````--this example assumes spriteMode(CORNER)
if getBlock(charX,charY-1)==solidBlock
or getBlock(charX+gridSize-1,charY-1)==solidBlock then
fall=false
end
``````

You should actually test two spots: the character's bottom-left corner and its bottom-right corner. that's what the second part of that if statement is doing; it's checking the bottom-right corner.

Now this all assumes that your character falls at a speed of less than one gridSize per frame. Normally, that's not a problem, but you will want to clamp your maximum velocity, just to make sure.

• Posts: 5,396

@tomxp411 (*)

• Posts: 577

But how could you make this into random terrian, sorry trying to process this in my nooby brain

• Posts: 157

Do you mean "random terrain" as in, stuff is just scattered around, or random as in "arbitrary", ie: terrain you design.

either way, you need a setBlock function, like this:

``````-- place block in a grid square
-- (0,0) is lower-left corner of grid
function setBlock(gridX,gridY,block)
map[gridx*gridSize+y]=block
end
``````

Based on the kinds of questions you're asking, I take it you're new to programming?

• edited August 2013 Posts: 157

(just ignore the dupe posts. the board kept returning an error, so I didn't realize I was actually posting successfully...)

• edited August 2013 Posts: 157

xx

• edited August 2013 Posts: 157

x

• Posts: 577

Thank you, and no I'm not new to programming, just new to lua and codea • Posts: 5,396

We all start off as Codea noobs 