Thought I'd share this with everyone because I know I'm not the first nor will I be the last person who will inquire about isometric games. So here's a simple demo.
The loadTilemap and wuline functions might look long or complicated, but really have nothing to do with the program. Wuline is just faster than DB's line command and provides me with better frame rates for the demo. And the tilemap function just makes it easier for me to load and splice a tilemap image.
Hold spacekey to display tilemap and use the mouse to select a tile. Arrow keys scroll the map. Left click to place a tile on the map, right click to remove a tile.
Attached is the tilemap image.
Rem Project: Isometric Map
Rem Created: Tuesday, August 07, 2012
REM Author: Phaelax
REM Special Thanks: Neuro Fuzzy and the rest of TGC community
rem load the tile map
imgMax = loadTilemap("d:\isometric_grass_and_water.png", 2, 64)
rem map array
dim map(10, 10)
rem build sample map
restore mapthing
for y = 1 to 10
for x = 1 to 10
read z
map(x, y) = z
next x
next y
rem for map scrolling
MapOffsetX = 320
MapOffsetY = 100
rem for map editing
_selectedTile = 2
sync on
do
cls
rem map scroll controls
if downkey() then dec MapOffsetY
if upkey() then inc MapOffsetY
if rightkey() then dec MapOffsetX
if leftkey() then inc MapOffsetX
mx = mousex() - MapOffsetX
my = mousey() - MapOffsetY
if spacekey()
rem display tile map on screen
paste image 1, 1, 1, 1
for x = 0 to 3
for y = 0 to 5
a = x*64
b = y*64
rem highlight map tile image under mouse
if mouseWithin(a, b, a+64, b+64) = 1
ink rgb(0,255,0),0
line a, b, a+64, b
line a, b+64, a+64, b+64
line a, b, a, b+64
line a+64, b, a+64, b+64
rem select map tile image
if mouseclick() = 1
_selectedTile = y*4 + x + 2
endif
endif
next y
next x
else
rem draw grid
for y = 0 to 9
for x = 0 to 9
tx = (x-y)*32
ty = (x+y)*16
drawIsoSquare(MapOffsetX + tx , MapOffsetY + ty)
next x
next y
rem draw tiles
for y = 0 to 9
for x = 0 to 9
tx = (x-y-1)*32
ty = (x+y-1)*16
if map(x+1,y+1) > 0 then paste image map(x+1,y+1), MapOffsetX + tx , MapOffsetY + ty, 1
next x
next y
rem get selected tile
mx = mousex()-MapOffsetX
my = mousey()-MapOffsetY
ink rgb(0,255,0),0
ix = (64*my + 32*mx) / (64*32)
iy = (64*my - 32*mx) / (64*32)
rem place tile on map
if mouseclick() = 1
if ix >= 0 and ix < 10 and iy >= 0 and iy < 10
map(ix+1, iy+1) = _selectedTile
endif
endif
rem erase tile from map
if mouseclick() = 2
if ix >= 0 and ix < 10 and iy >= 0 and iy < 10
map(ix+1, iy+1) = 0
endif
endif
rem draw selected tile
x = (ix-iy)*32 + MapOffsetX
y = (ix+iy)*16 + MapOffsetY
line x,y,x-32,y+16
line x,y,x+32,y+16
line x,y+32,x-32,y+16
line x,y+32,x+32,y+16
endif
rem display selected tile image
paste image _selectedTile, 640-64, 0, 1
set cursor 0,0
print "FPS: ",screen fps()
print mousex(),":",mousey()
print ix," : ",iy
print imgMax
sync
loop
function mouseWithin(x1, y1, x2, y2)
if mousex() > x1 and mousex() < x2 and mousey() > y1 and mousey() < y2 then exitfunction 1
endfunction 0
function drawIsoSquare(x, y)
wuline(x,y,x-32,y+16)
wuline(x,y,x+32,y+16)
wuline(x,y+32,x-32,y+16)
wuline(x,y+32,x+32,y+16)
endfunction
REM ===============================================================
REM Loads the specified image into a memblock and extracts
REM individual tiles, storing them starting with 'imgOffset'.
REM 'imgOffset' should start with 2 or higher, unless the variable
REM 'imgNoMap' at the top of the function is changed.
REM
REM Returns: Last image number used
REM ===============================================================
function loadTilemap(filename as string, imgOffset as integer, tileSize as integer)
rem these variables can be changed to fit your needs if these
rem numbers are already used elsewhere in your program
local memNoMap = 1
local memNoTile = 2
local imgNoMap = 1
local color as dword
rem load the tilemap image
load image filename, imgNoMap
rem Create the memblock to store the individual tiles
make memblock memNoTile, 12 + tileSize*tileSize*4
write memblock dword memNoTile, 0, tileSize
write memblock dword memNoTile, 4, tileSize
write memblock dword memNoTile, 8, 32
rem Create memlbock from the tilemap image
make memblock from image memNoMap, imgNoMap
imgWidth = memblock dword(memNoMap, 0)
imgHeight = memblock dword(memNoMap, 4)
rem determine how many tile rows and columns there are in the image
tileCols = imgWidth / tileSize
tileRows = imgHeight / tileSize
rem tile offset calculations
colTileOffset = tileSize*4
rowTileOffset = imgWidth*4*tileSize
rem loop through the tiles in the image
for y = 0 to tileRows-1
for x = 0 to tileCols-1
col = x*colTileOffset
row = y*rowTileOffset
rem tile offset within the image
tileOffset = row + col + 12
rem Extract pixel data from tilemap and store
rem a "tileSize by tileSize" image tile into
rem the other memblock
for iy = 0 to tileSize-1
for ix = 0 to tileSize*4-1 step 4
ty = iy*imgWidth*4
pos = tileOffset + ty + ix
rem extra pixel color from larger tilemap
color = memblock dword(memNoMap, pos)
tilePos = iy*tileSize*4 + ix + 12
rem write pixel color to smaller tile image
write memblock dword memNoTile, tilePos, color
next ix
next iy
rem create an image from tile memblock then repeat process
make image from memblock imgOffset, memNoTile
inc imgOffset, 1
next x
next y
rem free up memory
delete memblock memNoMap
delete memblock memNoTile
rem since DB can't handle expressions in the endfunction
dec imgOffset, 1
endfunction imgOffset
REM Xiaolin Wu's line algorithm
function wuline(x1,y1,x2,y2)
local dx as float
local dy as float
local xend as float
local yend as float
local xgap as float
local ygap as float
local xpxl1 as float
local ypxl1 as float
local xpxl2 as float
local ypxl2 as float
local intery as float
local interx as float
dx = x2-x1
dy = y2-y1
if abs(dx) > abs(dy)
rem handle horizontal lines
if x2 < x1
ax = x1
x1 = x2
x2 = ax
ay = y1
y1 = y2
y2 = ay
endif
gradient# = dy / dx
rem handle first endpoint
xend = ceil(x1)
yend = y1 + gradient# * (xend-x1)
xgap = 1.0 - fract#(x1 + 0.5)
xpxl1 = xend : `used in main loop
ypxl1 = int(yend)
f# = 1-fract#(yend)*xgap : `brightness
c = 255*f#
ink rgb(c,c,c),0
box xpxl1, ypxl1, xpxl1+1, ypxl1+1
rem brightness: fract#(yend)*xgap
f# = fract#(yend)*xgap : `brightness
c = 255*f#
ink rgb(c,c,c),0
box xpxl1, ypxl1+1,xpxl1+1, ypxl1+2
intery = yend + gradient# : `first y-intersection for main loop
rem handle second endpoint
xend = ceil(x2)
yend = y2 + gradient# * (xend-x2)
xgap = 1.0 - fract#(x2 + 0.5)
xpxl2 = xend : `used in main loop
ypxl2 = int(yend)
f# = 1-fract#(yend)*xgap : `brightness
c = 255*f#
ink rgb(c,c,c),0
box xpxl2, ypxl2, xpxl2+1, ypxl2+1
f# = fract#(yend)*xgap : `brightness
c = 255*f#
ink rgb(c,c,c),0
box xpxl2, ypxl2+1, xpxl2+1, ypxl2+2
rem main loop
a = xpxl1+1
b = xpxl2-1
for x = a to b
f# = 1-fract#(intery) : `brightness
c = 255*f#
ink rgb(c,c,c),0
box x, intery, x+1, intery+1
f# = fract#(intery) : `brightness
c = 255*f#
ink rgb(c,c,c),0
box x, intery+1, x+1, intery+2
intery = intery + gradient#
next x
else
rem handle vertical lines
if y2 < y1
ax = x1
x1 = x2
x2 = ax
ay = y1
y1 = y2
y2 = ay
endif
gradient# = dx / dy
ink rgb(255,0,0),0
rem handle first endpoint
yend = ceil(y1)
xend = x1 + gradient# * (yend-y1)
ygap = 1.0 - fract#(y1 + 0.5)
xpxl1 = int(xend)
ypxl1 = yend
f# = 1-fract#(xend)*ygap : `brightness
c = 255*f#
ink rgb(c,c,c),0
box xpxl1, ypxl1, xpxl1+1, ypxl1+1
f# = fract#(xend)*ygap : `brightness
c = 255*f#
ink rgb(c,c,c),0
box xpxl1, ypxl1+1, xpxl1+1, ypxl1+2
interx = xend + gradient# : `first y-intersection for main loop
rem handle second endpoint
yend = ceil(y2)
xend = x2 + gradient# * (yend-y2)
ygap = fract#(y2 + 0.5)
xpxl2 = int(xend)
ypxl2 = yend
f# = 1-fract#(xend)*ygap : `brightness
c = 255*f#
ink rgb(c,c,c),0
box xpxl2, ypxl2, xpxl2+1, ypxl2+1
f# = fract#(xend)*ygap : `brightness
c = 255*f#
ink rgb(c,c,c),0
box xpxl2, ypxl2+1, xpxl2+1, ypxl2+2
rem main loop
a = ypxl1+1
b = ypxl2-1
for y = a to b
f# = 1-fract#(interx) : `brightness
c = 255*f#
ink rgb(c,c,c),0
box interx, y, interx+1, y+1
f# = fract#(interx) : `brightness
c = 255*f#
ink rgb(c,c,c),0
box interx+1, y, interx+2, y+1
interx = interx + gradient#
next y
endif
endfunction
rem used for wuline function
function fract#(x as float)
a# = x - int(x)
endfunction a#
mapthing:
data 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
data 2, 2, 2, 6, 18,7, 2, 2, 2, 2
data 2, 2, 2, 17,25,19,2, 2, 2, 2
data 2, 2, 2, 21,16,8,2, 2, 2, 2
data 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
data 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
data 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
data 18,18,18,14,18,14,18,18,14,18
data 25,25,25,25,25,25,25,25,25,25
data 25,25,25,25,25,25,25,25,25,25
"You're not going crazy. You're going sane in a crazy world!" ~Tick