Skip to content

Instantly share code, notes, and snippets.

@dermotbalson
Created May 8, 2013 06:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save dermotbalson/5538596 to your computer and use it in GitHub Desktop.
Save dermotbalson/5538596 to your computer and use it in GitHub Desktop.
Town 203
--# Notes
--[[
These are notes for 3D Town version 2.02, 8 May 2012 by Ignatz
DESCRIPTION
This project allows you to create a 3D map with buildings you can walk around, and through
It does this by rotating the X axis so the Y axis projects into the screen
You add buildings in Map, using the functions in Building
NAVIGATION
The navigation can be changed to suit yourself. It is programmed in the touched function, along with a couple of other lines of code marked with "navigation" so you can find them
The navigation provided here works as follows:
* touch the top 1/4 or bottom 1/4 of the screen to move forward or backward.
* touch again to increase/ decrease speed.
* touch the left 1/4 or right 1/4 of the screen to turn left or right.
* touch again to turn faster or slower
* to stop moving and turning, touch the centre of the screen.
HOW TO USE IT - PREPARATION
1. You need all the images you are going to use, in your Dropbox or Documents account. They can
have any name as long as it is prefixed with "map-", so the program can find them.
If you choose Documents, change the imageFolder variable in setup, in the Main tab
2. You need to figure out how to scale each image (see below)
** Scaling your images **
What I mean by scaling is that your images will be different sizes, so they won't be in
proportion to each other. When you define your town, you specify a scaling fraction for each image.
For example, in the demo town, most of the stone walls come from large images that would produce
enormous stones if they were used as is, so I've used a scaling factor of less than 0.1.
In general, you don't need large images - quite small images will do fine, when you consider that
buildings are only about 100 pixels, and doors only 10 across.
So - you don't need to edit the images, just adjust the scaling fraction to make them look right.
Don't worry too much about it at first, you can do it by trial and error.
HOW TO USE IT - DEFINING BUILDINGS
First create an instance of the Building class and pass it the map to fill
b=Building(Map)
Note any name will do, it doesn't have to be b, but parameter in brackets does need to be Map
In the notes below, I've assumed you've used b as the name
** Basic box building (4 walls) **********************************************
What to use it for: house walls, hedges, fences
Syntax: b:BuildingWalls(x,y,w,d,h,i,sc,r)
where
x,y is bottom left corner (looking at map from starting position, and 0,0 is bottom left of map)
w = width along x axis (pixels)
d = depth along x axis (pixels)
h = height above ground along z axis (pixels)
i = image or string name of image (do not include library name)
sc = image scaling factor (see above) 0-1
r = the roof pitch in degrees, defaults to 15 (normal house is 10-15)
** Wall colour tint **********************************************
What to use it for: tint the outer walls any colour
Syntax: b:AddTint(c)
where c = colour (use a low alpha, eg 50)
** Building interior **********************************************
What to use it for - to create a plastered interior, it will draw an interior set of walls
using a chosen image
Syntax: b:BuildingInteriorWalls(i,sc,c)
where
i = image or string name of image (do not include library name)
sc = image scaling factor (see above) 0-1
c = whether to draw a ceiling as well (omit if not required, else true)
** Horizontal level **********************************************
What to use it for: surface of map, any horizontal 2D surface
Syntax: b:Level(x,y,w,d,z,i,sc)
where
x,y is bottom left corner (looking at map from starting position, and 0,0 is bottom left of map)
w = width along x axis (pixels)
d = depth along x axis (pixels)
z = height above floor
i = image or string name of image (do not include library name)
sc = image scaling factor (see above) 0-1
Note - for a floor surface, set z=0.1 or similarly small. You can also use level to create ceilings inside buildings by setting z=height of walls.
** Roof **********************************************
Syntax: b:Roof(o,i,sc)
where
o = overhang, number of pixels by which roof is wider than walls
i = image or string name of image (do not include library name)
sc = image scaling factor (see above) 0-1
** Floor (interior) **********************************************
Syntax: b:Floor(i,sc)
where
i = image or string name of image (do not include library name)
sc = image scaling factor (see above) 0-1
** Extras for houses (doors, windows..) **********************************************
What to use it for - anything attached to the wall of a building
Syntax: b:AddFeature(n,x,y,w,h,i,d)
where
n = wall to use. 1=front wall 2=left 3=right 4=back (as viewed from starting position)
x,y is bottom left corner (looking at map from starting position, and 0,0 is bottom left of map)
w = width along x axis (pixels)
h = height above ground along z axis (pixels)
i = image or string name of image (do not include library name)
d = true if you want it to appear on the interior side of the wall as well
** Stand alone features **********************************************
What to use it for: images that aren't attached to anything, eg a dog
Syntax: b:AddImage(x,y,w,i,r)
where
x,y is bottom left corner (looking at map from starting position, and 0,0 is bottom left of map)
w = width of object (pixels)
i = image or string name of image (do not include library name)
r = true if image should always rotate to face the user
--]]
--# Main
-- Walkthrough main
function setup()
if Backup then Backup("Town 203") end --my backup software
rad=math.pi/180
-- USER SETTINGS HERE -----
posX,posY,posZ=140,20,-20 --starting position (Y and Z are transposed, Y is vertical eye position)
--Note that z also moves "backwards", ie to go forward ,you reduce z, not increase it
angle=0 --initial angle, 0 faces forward
imageFolder="Dropbox"
---END OF USER SETTINGS---
d,da=0,0 --navigation
Map={}
SetupMap()
gb=0 --garbage collection, keeps memory down
parameter.integer("FPS",0,60,60)
parameter.integer("Elevation",0,500,15) -- allow user to vary height of viewpoint
parameter.text("Memory")
print("Touch left, right of screen to turn, top/bottom to go forward/back")
end
function draw()
background(175, 206, 223, 50)
spriteMode(CORNER)
pushMatrix()
pushStyle()
perspective(30, WIDTH/HEIGHT)
posY=Elevation
--navigation
angle=angle+da
posX,posZ=posX+d*math.sin(angle*rad),posZ-d*math.cos(angle*rad)
--end of navigation
--look in the same direction as we are facing
lookX,lookY,lookZ=posX+1000*math.sin(angle*rad),10,posZ-1000*math.cos(angle*rad)
camera(posX,posY,posZ,lookX,lookY,lookZ, 0,1,0)
rotate(-90,1,0,0) --rotate so map is drawn into the screen instead of up it as normal - per 3D lab example
fill(255)
for i,mm in pairs(Map) do
--rotate free standing objects if required, so they face us
if mm.x~=nil then
pushMatrix()
translate(mm.x,mm.y,0)
rotate(angle,0,0,1)
mm.m:draw()
popMatrix()
else
mm.m:draw()
end
end
popStyle()
popMatrix()
FPS=FPS*.9+(1/DeltaTime)*.1
Memory=gcinfo()
gb=gb+1 if gb%1000==0 then collectgarbage() end
end
--basic navigation, see Notes tab
function touched(touch)
local center=true
if touch.x<WIDTH/4 then
da=da-.03
center=false
elseif touch.x>WIDTH*3/4 then
da=da+.03
center=false
end
if touch.y<HEIGHT/4 then
d=d-.05
center=false
elseif touch.y>HEIGHT*3/4 then
d=d+.05
center=false
end
if center then d=0 da=0 end
end
--# Building
Building = class()
function Building:init(m)
self.MeshTable=m
self.exists=self:ImageExists()
end
--draw a basic box with a given texture
--a box consists of 24 triangles, made up of the 8 corner vertices
--x,y is bottom left corner (looking at map from starting position, and 0,0 is bottom left of map)
--w = width along x axis (pixels)
--d = depth along x axis (pixels)
--h = height above ground along z axis (pixels)
--i = image or string name of image (do not include library name)
--sc = image scaling factor (see above) 0-1
--r = the roof pitch in degrees, defaults to 15 (normal house is 10-15)
--s is whether we want to store the building co-ords for future use - only used by BuildingInteriorWalls
function Building:BuildingWalls(x,y,w,d,h,i,sc,r,s)
--store data first
if s==nil then --don't store if s is set
self.w={}
self.w.x1,self.w.y1,self.w.z1=x ,y ,0
self.w.x2,self.w.y2,self.w.z2=x+w,y+d,h
self.w.w,self.w.d,self.w.h=w,d,h
self.w.pitch=r
end
local img,colr
img=self:GetTexture(i)
if type(i)=="string" then
colr=color(255)
else
sc=1
local r,g,b,a=img:get(1,1)
colr=color(r,g,b,a)
end
self.w.img,self.w.sc=img,sc
--now create rectangular box
local v,t={},{} --vertices and texture mappings
--front wall
self:AddWall(x,y,0,x+w,y,h,img,sc,v,t)
--left side
self:AddWall(x,y,0,x,y+d,h,img,sc,v,t)
--right side
self:AddWall(x+w,y,0,x+w,y+d,h,img,sc,v,t)
--back side
self:AddWall(x,y+d,0,x+w,y+d,h,img,sc,v,t)
--add ends
if r then self:AddRoofEnds(img,sc) end
--add to mesh
self:AddToMesh(v,t,img,colr)
end
--Draw interior walls and ceiling
--i = image or string name of image (do not include library name)
--sc = image scaling factor (see above) 0-1
--c = whether to draw a ceiling as well (omit if not required, else true)
function Building:BuildingInteriorWalls(i,sc,c)
local margin=0.05
local x,y,w,d,h=self.w.x1+margin,self.w.y1+margin,self.w.w-margin*2,self.w.d-margin*2,self.w.h
self:BuildingWalls(x,y,w,d,h,i,sc,nil,true) --last param is true so we don't store bldg coords
if c then self:Level(x,y,w,d,h,i,sc) end --ceiling if requested
end
--draws an interior floor surface
--i = image or string name of image (do not include library name)
--sc = image scaling factor (see above) 0-1
function Building:Floor(i,sc)
local margin=0.05
local x,y,w,d,h=self.w.x1+margin,self.w.y1+margin,self.w.w-margin*2,self.w.d-margin*2,self.w.h
self:Level(x,y,w,d,margin,i,sc)
end
--this function is bulky mainly because of the scaling of images means they need to be tiled
--ie you may need several copies next to each other (and a fractional bit at the end)
--we have to calculate where each tile goes, in each triangle
--add to this the fact that the wall may be horizontal (ie x1~=X2, y1=y2) or vertical (x1=x2,y1~=y2)
function Building:AddWall(x1,y1,z1,x2,y2,z2,img,sc,v,t)
sc=sc or 1
local imgW,imgH=img.width*sc,img.height*sc
local nX,nY,nZ=(x2-x1)/imgW,(y2-y1)/imgW,(z2-z1)/imgH --number of tiles required in x and y axes
for xx=0,nX do
fX=math.min(1,nX-xx) --fractional part of tile, x axis
xx1,xx2=x1+xx*imgW,x1+(xx+fX)*imgW
for yy=0,nY do
fY=math.min(1,nY-yy) --fractional part of tile, y axis
yy1,yy2=y1+yy*imgW,y1+(yy+fY)*imgW
for zz=0,nZ do
fZ=math.min(1,nZ-zz) --fractional part of tile, in Z axis
zz1,zz2=z1+zz*imgH,z1+(zz+fZ)*imgH
--create vectors and texture mappings
v[#v+1]=vec3(xx1,yy1,zz1) t[#t+1]=vec2(0,0)
v[#v+1]=vec3(xx2,yy2,zz1) t[#t+1]=vec2(fX+fY,0) --fX and fY added because only one can be nonzero
v[#v+1]=vec3(xx1,yy1,zz2) t[#t+1]=vec2(0,fZ)
v[#v+1]=vec3(xx1,yy1,zz2) t[#t+1]=vec2(0,fZ)
v[#v+1]=vec3(xx2,yy2,zz2) t[#t+1]=vec2(fX+fY,fZ)
v[#v+1]=vec3(xx2,yy2,zz1) t[#t+1]=vec2(fX+fY,0)
end
end
end
end
--similar to wall but horizontal, only using x and y axes
--x,y is bottom left corner (looking at map from starting position, and 0,0 is bottom left of map)
--w = width along x axis (pixels)
--d = depth along x axis (pixels)
--z = height above floor
--i = image or string name of image (do not include library name)
--sc = image scaling factor (see above) 0-1
function Building:Level(x,y,w,d,z,i,sc)
sc=sc or 1
local img=self:GetTexture(i)
local v,t={},{}
local imgW,imgH=img.width*sc,img.height*sc
local nX,nY=w/imgW,d/imgW
for xx=0,nX do
local fX=math.min(1,nX-xx)
local xx1,xx2=x+xx*imgW,x+(xx+fX)*imgW
for yy=0,nY do
local fY=math.min(1,nY-yy)
local yy1,yy2=y+yy*imgW,y+(yy+fY)*imgW
v[#v+1]=vec3(xx1,yy1,z) t[#t+1]=vec2(0,0)
v[#v+1]=vec3(xx2,yy1,z) t[#t+1]=vec2(fX,0)
v[#v+1]=vec3(xx2,yy2,z) t[#t+1]=vec2(fX,fY)
v[#v+1]=vec3(xx2,yy2,z) t[#t+1]=vec2(fX,fY)
v[#v+1]=vec3(xx1,yy2,z) t[#t+1]=vec2(0,fY)
v[#v+1]=vec3(xx1,yy1,z) t[#t+1]=vec2(0,0)
end
end
--add to mesh
self:AddToMesh(v,t,img)
end
--puts image on wall n at position x,y with dimensions w,h, d is there for the future if we draw insides
--(if true means image is mirrored on the inside)
--n=1 front wall, 2=left, 3=right, 4=back, viewed from front perspective
--i is image name
function Building:AddFeature(n,x,y,w,h,i,d)
local img=self:GetTexture(i)
sc=w/img.width
h=sc*img.height
local v,t={},{}
local margin=0.2
if n==1 then --front
local yy=self.w.y1-margin
self:AddWall(self.w.x1+x,yy,y,self.w.x1+x+w,yy,y+h,img,sc,v,t)
if d then
self:AddWall(self.w.x1+x,self.w.y1+margin,y,self.w.x1+x+w,self.w.y1+margin,y+h,img,sc,v,t)
end
elseif n==2 then --left
local xx=self.w.x1-margin
self:AddWall(xx,self.w.y2-x-w,y,xx,self.w.y2-x,y+h,img,sc,v,t)
if d then
self:AddWall(self.w.x1+margin,self.w.y2-x-w,y,self.w.x1+margin,self.w.y2-x,y+h,img,sc,v,t)
end
elseif n==3 then --right
local xx=self.w.x2+margin
self:AddWall(xx,self.w.y1+x,y,xx,self.w.y1+x+w,y+h,img,sc,v,t)
if d then
self:AddWall(self.w.x2-margin,self.w.y1+x,y,self.w.x2-margin,self.w.y1+x+w,y+h,img,sc,v,t)
end
elseif n==4 then --back
local yy=self.w.y2+margin
self:AddWall(self.w.x2-x-w,yy,y,self.w.x2-x,yy,y+h,img,sc,v,t)
if d then
self:AddWall(self.w.x2-x-w,self.w.y2-margin,y,self.w.x2-x,self.w.y2-margin,y+h,img,sc,v,t)
end
end
--add to mesh
self:AddToMesh(v,t,img)
end
--adds roof
--o = overhang, number of pixels by which roof is wider than walls
--i = image or string name of image (do not include library name)
--sc = image scaling factor (see above) 0-1
function Building:Roof(o,i,s)
local p=self.w.pitch*math.pi/180 --15 degree roof pitch
o=o or 3
s=s or 1
local img=self:GetTexture(i)
--self:Level(self.w.x1-o,self.w.y1-o,self.w.x2-self.w.x1+o*2,self.w.y2-self.w.y1+o*2,self.w.z2,i,s)
local iw,id,ih
iw=math.max(self.w.w,self.w.d)+o*2
id=(iw/2)/math.cos(p)
ih=(iw/2)*math.tan(p)
local roof=image(iw,id)
setContext(roof)
local nw,nd=math.floor(iw/(s*roof.width)+.999),math.floor(id/(s*roof.height)+.999)
local ss=s*roof.width
for i=1,iw,nw do
for j=1,ih,nd do
sprite(img,i,j,ss)
end
end
setContext()
local v,t={},{}
if self.w.w>self.w.d then
v[1]=vec3(self.w.x1-o,self.w.y1-o,self.w.h) t[1]=vec2(0,0)
v[2]=vec3(self.w.x1-o,self.w.y1+self.w.d/2,self.w.h+ih) t[2]=vec2(0,1)
v[3]=vec3(self.w.x2+o,self.w.y1-o,self.w.h) t[3]=vec2(1,0)
v[4]=vec3(self.w.x2+o,self.w.y1-o,self.w.h) t[4]=vec2(1,0)
v[5]=vec3(self.w.x2+o,self.w.y1+self.w.d/2,self.w.h+ih) t[5]=vec2(1,1)
v[6]=vec3(self.w.x1-o,self.w.y1+self.w.d/2,self.w.h+ih) t[6]=vec2(0,1)
v[7]=vec3(self.w.x1-o,self.w.y2+o,self.w.h) t[7]=vec2(0,0)
v[8]=vec3(self.w.x1-o,self.w.y2-self.w.d/2,self.w.h+ih) t[8]=vec2(0,1)
v[9]=vec3(self.w.x2+o,self.w.y2+o,self.w.h) t[9]=vec2(1,0)
v[10]=vec3(self.w.x2+o,self.w.y2+o,self.w.h) t[10]=vec2(1,0)
v[11]=vec3(self.w.x2+o,self.w.y2-self.w.d/2,self.w.h+ih) t[11]=vec2(1,1)
v[12]=vec3(self.w.x1-o,self.w.y2-self.w.d/2,self.w.h+ih) t[12]=vec2(0,1)
else
v[1]=vec3(self.w.x1-o,self.w.y1-o,self.w.h) t[1]=vec2(0,0)
v[2]=vec3(self.w.x1+self.w.w/2,self.w.y1-o,self.w.h+ih) t[2]=vec2(0,1)
v[3]=vec3(self.w.x1-o,self.w.y2+o,self.w.h) t[3]=vec2(1,0)
v[4]=vec3(self.w.x1-o,self.w.y2+o,self.w.h) t[4]=vec2(1,0)
v[5]=vec3(self.w.x1+self.w.w/2,self.w.y2+o,self.w.h+ih) t[5]=vec2(1,1)
v[6]=vec3(self.w.x1+self.w.w/2,self.w.y1-o,self.w.h+ih) t[6]=vec2(0,1)
v[7]=vec3(self.w.x2+o,self.w.y1-o,self.w.h) t[7]=vec2(0,0)
v[8]=vec3(self.w.x2-self.w.w/2,self.w.y1-o,self.w.h+ih) t[8]=vec2(0,1)
v[9]=vec3(self.w.x2+o,self.w.y2+o,self.w.h) t[9]=vec2(1,0)
v[10]=vec3(self.w.x2+o,self.w.y2+o,self.w.h) t[10]=vec2(1,0)
v[11]=vec3(self.w.x2-self.w.w/2,self.w.y2+o,self.w.h+ih) t[11]=vec2(1,1)
v[12]=vec3(self.w.x2-self.w.w/2,self.w.y1-o,self.w.h+ih) t[12]=vec2(0,1)
end
--add to mesh
self:AddToMesh(v,t,img)
end
function Building:AddRoofEnds(img,sc)
local v,t={},{} --vertices and texture mappings
local p=self.w.pitch*math.pi/180 --15 degree roof pitch
local imax,imin,iw,ih
imax=math.max(self.w.w,self.w.d)
imin=math.min(self.w.w,self.w.d)
ih=(imax/2)*math.tan(p)
local e=image(imin,ih)
setContext(e)
local nw,nd=math.floor(imin/(sc*img.width)+.999),math.floor(ih/(sc*img.height)+.999)
local s=img.width*sc
for i=1,imin,nw do
for j=1,ih,nd do
sprite(img,i,j,s)
end
end
setContext()
if self.w.w>self.w.d then
v[1]=vec3(self.w.x1,self.w.y1,self.w.h) t[1]=vec2(0,0)
v[2]=vec3(self.w.x1,self.w.y1+self.w.d/2,self.w.h+ih) t[2]=vec2(.5,1)
v[3]=vec3(self.w.x1,self.w.y2,self.w.h) t[3]=vec2(1,0)
v[4]=vec3(self.w.x2,self.w.y1,self.w.h) t[4]=vec2(0,0)
v[5]=vec3(self.w.x2,self.w.y1+self.w.d/2,self.w.h+ih) t[5]=vec2(.5,1)
v[6]=vec3(self.w.x2,self.w.y2,self.w.h) t[6]=vec2(1,0)
else
v[1]=vec3(self.w.x1,self.w.y1,self.w.h) t[1]=vec2(0,0)
v[2]=vec3(self.w.x1+self.w.w/2,self.w.y1,self.w.h+ih) t[2]=vec2(.5,1)
v[3]=vec3(self.w.x2,self.w.y1,self.w.h) t[3]=vec2(1,0)
v[4]=vec3(self.w.x1,self.w.y2,self.w.h) t[4]=vec2(0,0)
v[5]=vec3(self.w.x1+self.w.w/2,self.w.y2,self.w.h+ih) t[5]=vec2(.5,1)
v[6]=vec3(self.w.x2,self.w.y2,self.w.h) t[6]=vec2(1,0)
end
--add to mesh
self:AddToMesh(v,t,img,colr)
end
--adds tint to outside of building
function Building:AddTint(c)
local e=image(10,10)
local margin=0.1
pushStyle()
setContext(e)
strokeWidth(0)
fill(c)
rect(-1,-1,e.width+2,e.height+2)
setContext()
popStyle()
self:BuildingWalls( self.w.x1-margin,
self.w.y1-margin,
self.w.w+margin*2,
self.w.d+margin*2,
self.w.h,
e,1,self.w.pitch)
end
--adds stand alone image
--x,y is bottom left corner (looking at map from starting position, and 0,0 is bottom left of map)
--w = width of object (pixels)
--i = image or string name of image (do not include library name)
--r = true if image should always rotate to face the user
function Building:AddImage(xx,yy,w,i,r)
local img
img=self:GetTexture(i)
local h=w*img.height/img.width
local v,t={},{}
local x,y
if r then x,y=0,0 else x,y=xx,yy end
v[1]=vec3(x,y,0) t[1]=vec2(0,0)
v[2]=vec3(x,y,h) t[2]=vec2(0,1)
v[3]=vec3(x+w,y,0) t[3]=vec2(1,0)
v[4]=vec3(x+w,y,0) t[4]=vec2(1,0)
v[5]=vec3(x+w,y,h) t[5]=vec2(1,1)
v[6]=vec3(x,y,h) t[6]=vec2(0,1)
if r then
self:AddToMesh(v,t,img,nil,xx,yy)
else
self:AddToMesh(v,t,img,nil)
end
end
function Building:GetTexture(i)
if type(i)=="string" then
if self.exists(i)==false then print("ERROR: "..i.." does NOT exist") end
return readImage(imageFolder..":"..i)
else
return i
end
end
function Building:ImageExists(i)
local s=spriteList(imageFolder)
local sList={}
for i=1,#s do
if string.sub(s[i],1,4)=="map-" then sList[s[i]]=true end
end
return function(i)
if sList[i]==true then return true else return false end
end
end
function Building:AddToMesh(v,t,img,c,x,y)
local mm={}
mm.m=mesh()
local colr=c or color(255,255,255,255)
mm.m:setColors(colr)
mm.m.vertices=v
mm.m.texCoords=t
mm.m.texture=img
mm.type=type or "b"
mm.x,mm.y=x,y
table.insert(self.MeshTable,mm)
collectgarbage()
end
--# Map
function SetupMap()
b=Building(Map)
--make wall surrounding map
local i="map-hedge2"
b:BuildingWalls(0,0,WIDTH,1,15,i,.15)
b:BuildingWalls(0,0,1,HEIGHT,15,i,.15)
b:BuildingWalls(WIDTH,0,1,HEIGHT,15,i,.15)
b:BuildingWalls(0,HEIGHT,WIDTH,1,15,i,.15)
--tile the ground
b:Level(0,0,WIDTH,HEIGHT,0,"map-gravel11",.05)
--first building
b:BuildingWalls(20,20,100,100,30,"map-stone1",.1,15)
b:AddFeature(3,50,0,10,20,"map-door5")
b:AddFeature(3,25,10,10,20,"map-window2")
b:AddFeature(3,75,10,10,20,"map-window2")
b:Roof(3,"map-roof1",.5)
--second building
b:BuildingWalls(20,140,100,70,30,"map-whitewall2",.05,15)
b:AddTint(color(255,255,0,50))
b:AddFeature(3,30,0,10,20,"map-door1")
b:AddFeature(3,5,5,15,10,"map-poster1")
b:AddFeature(4,1,0.5,8,10,"map-Ignatz1")
b:AddFeature(4,80,0,8,10,"map-door10")
b:AddFeature(4,30,5,25,10,"map-window3")
b:Roof(2,"map-roof1",.5)
--third building
b:BuildingWalls(150,20,100,150,25,"map-whitewall1",.05,15)
b:BuildingInteriorWalls("map-whitewall1",.05,true)
b:AddTint(color(0,0,255,20))
b:AddFeature(2,30,8,10,15,"map-window5",true)
b:AddFeature(2,120,8,10,15,"map-window5",true)
b:AddFeature(2,80,0,10,20,"map-door10",true)
b:Floor("map-carpet1",.1)
b:Roof(2,"map-roof1")
b:AddImage(180,140,10,"map-dog4",true)
b:BuildingWalls(150,200,1,1,25,"map-bark1",.02)
b:BuildingWalls(200,200,1,1,25,"map-bark1",.02)
b:BuildingWalls(250,200,1,1,25,"map-bark1",.02)
b:Level(148,170,104,32,25,"map-roof1",.05)
--fourth building
b:BuildingWalls(150,230,70,60,20,"map-whitewall2",.05,15)
b:AddTint(color(231, 137, 20, 25))
b:AddFeature(2,15,5,6,15,"map-window7")
b:AddFeature(2,40,0,10,20,"map-door2")
b:Roof(2,"map-roof2")
b:Level(153,205,65,27,.1,"map-garden1",.05)
--extras
b:Level(130,150,10,10,.1,"map-grate1",.05)
b:Level(2,235,90,HEIGHT-235,.1,"map-grass1",.1)
b:AddImage(60,450,10,"map-dog4",true)
b:BuildingWalls(92,235,0.5,HEIGHT-235,10,"map-fence1",.1)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment