ok so, the rotation of the player is now handled in the array.
ive illiminated the getimage comands from my main loop. but ive ended up using sprites in x as well as y.
it tells you how many sprites its using on the screen and its loads. and thats where its slowing down now i think.
it would be nice to think that the app kit will handle sprites faster . i believe they are individual 3d objects for each sprite in dbpro. but any time you want to draw 4000+ sprites i would expect trouble. its hard to speculate how to work around that until we get our hands on it.
all of the drawing to the screen is done in one part of the program and because of x as well as y coordinates it would be easier to match up with a wall drawing part of a program. it would be possible to make it only draw the floor in a vertical colum once it had reached the bottom of a wall.
do try photo textures with the prog. it looks funny. but go carefull as my random texture generator now saves out files.
so it might write over your textures if you dont switch it off.
incidently all the stuff about using the colour on a texture as point in space im sure i got into when i was looking at pixel
shaders. they work quite differently to other stuff ive seen. but you can get ideas to use in db by poking about in different stuff.
how slow are text commands? how much faster do our programs run when they arent writing the fps on the screen?
but seriously ,ive switched off the displays to speed it up a bit but switching them back on gives more of an idea of whats going on.
its in two parts again first to makes the data about the depth from screen. run first
sync on :
sync rate 0 :
set display mode 480,320,32
`now im using a screen size of 480*320. im only using the bottom half so thats 480*160
`im also only grabbing every 4th pixel giving a res of 120*40
box 0,0,256,256,rgb(255,0,0),rgb(0,0,0),rgb(255,0,255),rgb(0,0,255)
get image 1,0,0,256,256
`first im making a texture im using the box command to draw it
`and then getting the image. by setting the rgb values ive created a gradient
`the image gets more blue as it goes horrizontaly and more red as it goes vertically
`by picking a pixel at any point we can tell where on the image it came from
`by looking at the rgb values. rgbb(point (x,y)) gives us the blue amount.
`a blue value of 0 gives us an x amount of 0 on the far left. a value of 128
`is in the middde of the image. the blue gives us horizontal positions and red vertical ones
playerangle=90
playerx=250
playery=250
gosub setup_plane
camy=10
dim depthdata(72,120,40,2)
`72 = rotations of camera . we move 5 degrees each time 5*72=360
`120 = x resolution
`40 = y resolution
`2 = the x and y at that point on screen
`even though im not grabbing as much data as i could the array is still 8.28 mb when saved to disk. thats
`kinda huge. last version when i only grabed 2 numbers for the x it was only 500k
`im gabbing all the extra x data so i can have a tile for each x and y point on screen . then i only have
` to choose what tile to put there not grab a new image each time.
`i could cut down on data by only looking at one stip in front of the player for each of 360 degrees
`instead of looking at all the x data to fill each side of the screen. i could use the angles either
`side of where the player is facing.
` i think this would lead to the same fishbowl distortions you get in raycasting
sync
gosub get_slices
save array "depth03.dat", depthdata(0)
`gosub get_slices
camhieght=25
do
gosub draw_slices
text 200,0,"its finished"
text 400,20,"fps"+str$(screen fps())+""
`text 900,0,"camy"+str$(camy)+""
if rightkey()=1 then drawangle=drawangle+1
if leftkey()=1 then drawangle=drawangle-1
if drawangle=72 then drawangle=0
if drawangle=-1 then drawangle=72
rotate camera 0,drawangle*5,0
sync
loop
setup_plane:
autocam off
position camera 0,30,0
make object plane 100,500,500
set object light 100,0
set object ambient 100,0
`turn off the lights so colours are same as texture
texture object 100,1
`the plane is textured with the gradient
rotate object 100,270,180,0
`the plane is fliped over so the gradient on texture goes the way i want
return
get_slices:
position camera 0,14,0
for angle=0 to 72
` im rotating the camera 5 degrees at a time so we only need 72 to do a rull 360 rotation
camera_angle = angle*5
rotate camera 4,camera_angle,0
`4 = ive tilted the camera down slightly so the plain goes all the way to the horizon
`this does muck up our perspective really. but at the low resolutions im getting it doesnt really show.
sync
for grabx=0 to 120
for graby=0 to 40
text 0,0,"its not finished"
graby2=(graby*4)
graby2=graby2+160
grabx2=grabx*4
blue1=rgbb(point (grabx2,graby2))
red1=rgbr(point (grabx2,graby2))
`slicedata(72,160,480,2)
depthdata(angle,grabx,graby,1)=blue1
depthdata(angle,grabx,graby,2)=red1
`dot grabx*4,graby2
line grabx*4,graby2, (grabx*4)+1,(graby2)+1
`those lines are points on the screen where colour data is taken from
text 10,100,"those dots are points on the screen"
text 10,120," where colour data is taken from"
next graby
next grabx
next angle
`we grab colour data at x and y points in screen that represent x and y points on the ground plane
`more info on this in previous version.
return
draw_slices:
`this bit draws lines in the top corner. this is the data we use to get the sprites
`now instead of moving up and down the lines move round and round.
`the lines are made of individual points with x and y cordinates
`we now have a representaion of rotation in a array with x and y points
`so we dont need to do any rotation maths just difine an angle to retrive the
`data from that viewing angle
for grabx3=0 to 120 `step 5
for graby3=0 to 40 `step 5
`xxxx=depthdata(drawangle,grabx,graby,1)
`yyyy=depthdata(drawangle,grabx,graby,2)
dot depthdata(drawangle,grabx3,graby3,1),depthdata(drawangle,grabx3,graby3,2)
next grabx3
next graby3
return
then in the same folder the second draws the 2d version.
sync on :
sync rate 0 :
`Version 2 or 0.002 or whatever
`Hang on. wasn't there something else i was ment to be doing!!
`using sprites to draw a 3dimensional floor. messing about.
`this program needs to load in data from a companion program. run that first in the same folder
`the other program makes data about different distances into the horizon
set display mode 1024,600,32
gosub draw_texture:
`CAUTION draw_texture now saves out images tex01.bmp to tex04.bmp
`so if you want to use your own textures then
`switch draw_texture off so you dont overwrite them.
`
dim levelmap(64,64)
gosub make_levelmap
next_free_image=1
teximage1=next_free_image
load image "tex01.bmp",next_free_image
next_free_image=next_free_image+1
teximage2=next_free_image
load image "tex02.bmp",next_free_image
next_free_image=next_free_image+1
teximage3=next_free_image
load image "tex03.bmp",next_free_image
next_free_image=next_free_image+1
teximage4=next_free_image
load image "tex04.bmp",next_free_image
next_free_image=next_free_image+1
next_free_image=next_free_image+1
`=========================================
`IMPORTANT STUFF
`=========================================
`spriteres is the horizontal and vertical interval between each tile drawn in screendraw:
`it should be a multiple of 4 . with 4 as lowest as that was the gaps we left when we got depthdata()
`this number can be changed while program runs
spriteres=12
spritedetail=2
`sprite detail controls how much image is on each sprite try changing it
`to 1 and also a high number like 8
`this number can NOT be changed while program runs.
`as the images are only grabbed before the main loop
spritesize=12
`this is the actual size of sprites in pixels.
`this number can be changed while program runs but it is reset to match the spritres when that is changed
`==========================================
ground_start_image=next_free_image
dim ground_array(260,260)
gosub put_images_in_array
`gosub get_floor_images
dim depthdata(72,120,40,2)
load array "depth03.dat",depthdata(0)
`load array!!!! make sure you run the other program to create the camera view data
playerangle=90
drawangle=32
playerx=1028
playery=1028
stepamount=4
`before the main loop
`we create the level map gosub make_levelmap:
`we get our images and put them in the texture array in gosub put_images_in_array: gosub get_floor_images:
`we load the depthdata from the other program
` in the main loop
` we get player_input:
` x and y data is used to update the gound array in gosub copy_texture_to_ground_array:
` then the perspective view is drawn in screendraw:
` optionally we can draw other helpfull stuff to screen remed out to help with speed
`gosub draw_levelmap
`gosub draw_slices
`gosub drawall
do
text 850,40,"spriteres "+str$(spriteres)+""
text 850,60,"spritesize "+str$(spritesize)+""
text 850,80,"sprites used "+str$(spritenumber)+""
text 850,100,"fps "+str$(screen fps())+""
text 600,0," arrow keys left/right rotate view"
text 600,20," arrow keys up/move fowards"
text 600,40," a/z keys spriteres"
text 600,60," s/x keys spritesize."
text 600,120,"x " +str$(playerx)+""
text 600,140,"y " +str$(playery)+""
text 600,160,"angle " +str$(drawangle)+""
`if playerx=128 or playerx=3900 then text 100,500,"edge of map reached. turn around"
`if playery=128 or playery=3900 then text 100,500,"edge of map reached. turn around"
gosub player_input
gosub screendraw
`gosub draw_levelmap
`draw_levelmap: draws levelmap(64,64) each number represents an image 1 to 4
`these are our tile textures see put images_in_array: and get_floor_textures:
`it draws a box around the player this shows the ground_array(255,255)
`gosub drawall
` unrem drawall to see a top down view of the tiles in the ground plan surronding the player
`gosub draw_slices
`draw_slices: draws the data from depthdata(72,120,40,2)
`it gives a top down view of all the points in the ground plain the player can see
`in the last version you could only look up. now you can see the rotation of the player
sync
loop
player_input:
if scancode()=30 and spriteres<20 then spriteres=spriteres+4;spritesize=spriteres;gosub hide_sprites;wait 200
if scancode()=44 and spriteres>5 then spriteres=spriteres-4;spritesize=spriteres;gosub hide_sprites;wait 200
`spriteres the horizontal and vertical interval between each tile drawn in screendraw:
if scancode()=31 and spritesize<50 then spritesize=spritesize+1;
if scancode()=45 and spritesize>2 then spritesize=spritesize-1;
`spritesize the size in pixels of each tile drawn in screendraw:
if rightkey()=1 then drawangle=drawangle+1
if leftkey()=1 then drawangle=drawangle-1
if drawangle=72 then drawangle=0
if drawangle=-1 then drawangle=72
`depthdata was created at angle intevals of 5 so we only need to go to 72 to rotate 360
if upkey()=1
` im using the depthdata to move fowards. looking in the depthdata at the current player rotation (drawangle)
`i know that a point in the middle of the screen is directly in front of the player
`60=center of screen in x. is half of 120
`30=y a bit up the screen
newx=depthdata(drawangle,60,30,1)
newy=depthdata(drawangle,60,30,2)
newx2=128-newx
newy2=128-newy
`128 is the center of groundarray half of 265 this is the players x and y in terms of the depthdata
`all of the points in the depth array will be more or less than 128, depending which way you face
`buy deleting 128 we get x and y values that represent a distance in front of player it could be plus or minus
playerx=playerx-(newx2/10)
playery=playery-(newy2/10)
`this distance is the subtracted from the player position to move them in that direction
` this way of moving foward is a bit off. there are dead spots where you wont move foward
`well you get the gist. its a bit like first person movment
if playerx<128 then playerx=128
if playery<128 then playery=128
if playerx>3900 then playerx=3900
if playery>3900 then playery=3900
`we limit how far the player can go in the map, they must always be 128 away from the edge
` so we can draw to the horizon whatever way they look
gosub copy_texture_to_ground_array
`now that the player has moved foward. we must update the ground around the player
`useing the level map and the texture array
endif
return
draw_texture:
`tried to make it media free
`if you cant be bothered to make a texture to try this program with this bit makes a random one
box 0,0,64,64,rgb(255,0,0),rgb(0,0,0),rgb(255,0,255),rgb(0,0,255)
for d= 1 to 10
ink rgb(rnd(255),rnd(255),rnd(255)),0
xa=rnd(64)
ya=rnd(64)
xb=xa+rnd(10)
yb=ya+rnd(10)
box xa,ya,xb,yb, rgb(rnd(255),rnd(255),rnd(255)),rgb(rnd(255),rnd(255),rnd(255)),rgb(rnd(255),rnd(255),rnd(255)),rgb(rnd(255),rnd(255),rnd(255))
next d
get image 1,0,0,256,256
save image "tex01.bmp",1
box 0,0,64,64,rgb(255,255,255),rgb(255,255,255),rgb(0,0,255),rgb(0,0,255)
for d= 1 to 10
ink rgb(rnd(255),rnd(255),rnd(255)),0
xa=rnd(64)
ya=rnd(64)
xb=xa+rnd(10)+10
yb=ya+rnd(10)+10
box xa,ya,xb,yb, rgb(0,0,rnd(155)),rgb(0,0,rnd(155)),rgb(0,0,rnd(155)+100),rgb(0,0,rnd(155)+100)
next d
get image 1,0,0,256,256
save image "tex02.bmp",1
box 0,0,64,64,rgb(0,0,0),rgb(255,255,255),rgb(155,155,155),rgb(155,155,155)
for d= 1 to 40
ink rgb(rnd(255),rnd(255),rnd(255)),0
xa=rnd(64)
ya=rnd(64)
xb=xa+rnd(10)
yb=ya+rnd(10)
grey=rnd(155)+100
box xa,ya,xb,yb, rgb(grey,grey,grey),rgb(grey,grey,grey),rgb(grey,grey,grey),rgb(grey,grey,grey)
next d
get image 1,0,0,256,256
save image "tex03.bmp",1
for d= 1 to 100
ink rgb(rnd(255),rnd(255),rnd(255)),0
xa=rnd(64)
ya=rnd(64)
xb=xa+rnd(10)
yb=ya+rnd(10)
box xa,ya,xa+xb,ya+yb
next d
get image 1,0,0,256,256
save image "tex04.bmp",1
ink rgb(255,255,255),0
return
put_images_in_array:
`this only happens before the main loop. all of the images used as textures are turned into tiles
`there are 4 textures of 64x64 pixels. the texture_array is used in copy_texture_to_ground_array:
`levelmap(x,y) is used to decide what texture is taken from texture_array2(10,64,64) to fill the ground_array(256,256)
dim texture_array2(10,64,64)
`texture_array2(texture number , x pixels ,y pixels)
getimage=teximage1
texnum=1`this will be used in get_floor_images: to fill the right slot in texture_array2(10,64,64)
gosub get_floor_images
ground_start_image=next_free_image
getimage=teximage2
texnum=2
gosub get_floor_images
ground_start_image=next_free_image
getimage=teximage3
texnum=3
gosub get_floor_images
ground_start_image=next_free_image
getimage=teximage4
texnum=4
gosub get_floor_images
return
get_floor_images:
`ground_start_image=next_free_image
next_free_image=ground_start_image
`im pasting multiple images so if an image is grabed that goes off the edge of the image
`it wont be black causing lines round the edge of each tile in the perspective view
paste image getimage,8,0
paste image getimage,8,8
paste image getimage,0,8
paste image getimage,0,0
`each texture is choped up in tiles, there will be 16x16 tiles
`each tile will represnt 4x4 pixels in the texture
`that is because the that is the spaceing we used to scan the screen in the other program.
`beacuase each tile has 4x4 pixels this will lead to a dithering effect when the tile s are drawn
`to the screen. by setting the spritedetail number at the start to 1 we would have one pixel tiles
`so each sprite would only have pixel. or we could grab images that are much bigger.
`to cut down on get image commands the tile images are only grabed at the start of the program
`so the sprite detail cannot be changed during the program with keys. but the size of the sprite can be changed
`because they overlap when big this will effect their apparent resolution.
`although there are only 16x16 tiles we want to know which tile represent any pixel in the image.
`the texture_array(10,64,64) is filled with image numbers of corrisponding images
`latter the texture array data will be used to fill the ground_array(x,y)
`the ground_array(x,y) is 256x256 so we can tile 16 64x64 image tiles into it
` rather than grabing images off the screen we can now look into an array and find out which image to use to represent
`that point in the array
stepamount=4
for xget= 0 to 64 step 4
for yget= 0 to 64 step 4
`ground_array(256,256)
get image next_free_image,xget,yget,xget+spritedetail,yget+spritedetail,3
for sx=xget to xget+ spriteres+1
for sy=yget to yget+ spriteres+1
if sx=<64
if sy=<64
texture_array2(texnum,sx,sy)=next_free_image
endif
endif
next sy
next sx
ground_end_image=next_free_image
next_free_image=next_free_image+1
next yget
next xget
gosub copy_texture_to_ground_array
return
copy_texture_to_ground_array:
`the ground array is the 256x256 area that surrounds the player
`we need to fill it with information about which bit of texture tile fills each point
for x= 0 to 255
for y= 0 to 255
newy=y+playery
newx=x+playerx
`by adding the playerx and playery to the x and y we know where each point in the ground array is in our level
mapx=newx/64
mapy=newy/64
levelsquare=levelmap(mapx,mapy)
`by dividing the x and y by 64 we know which tile each point in the map is over
remainderx=newx-(64*mapx)
remaindery=newy-(64*mapy)
`multiply mapx by 64 gives us the start x of that tile. take away from the actual player
`position tells you how far into that tile you are at that point
ground_array(x,y)=texture_array2(levelsquare,remainderx,remaindery)
`the texture array was filled before the main loop in get_floor_images:
`the texture array is full of image numbers these are coppied to ground array to be used
` by screendraw: to give sprites the correct image
next y
next x
return
screendraw:
` perspective view all of the spites in the 3d view are drawn here
spritenumber=10
for screenx=0 to 120 step spriteres/4
for screeny=0 to 40 step spriteres/4
screeny2=(screeny*4)
screeny2=screeny2+160+20
screenx2=screenx*4
xget2=depthdata(drawangle,screenx,screeny,1)
yget2=depthdata(drawangle,screenx,screeny,2)
`xget2 will be a number between 0 and 256 relating to point on the ground infront of the player
pasteno=ground_array(xget2,yget2)
`pasteno will be the image number of the tile of texture that represents that point in front
`the ground_array surrounds the player and is filled in copy_texture_to_ground_array: everytime the player moves
sprite spritenumber,screenx2+25,screeny2+100,pasteno
show sprite spritenumber
`the sprite may have been hidden when the spriteres was changed in player_input:
size sprite spritenumber,spritesize,spritesize
`the sprite can be scaled with the s/x keys but this is independent of number of sprites we use
` and hence the resolution, and also the image on the sprite. but does have an interesting effect
`
spritenumber=spritenumber+1
next graby
next grabx
` all of the drawing to screen happens here now. the slowdown seems to happen because of the volume of sprites
`the screen is now represnted in x and y rows. if you had a screen array with the hieghts of the wall sprite
`in each row we could tell it to only draw floor sprites at the bottom of each vertical row.
` we could have different versions of this part with smaller sprites at the horizon and bigger at the base of screen
` another posibility is to only have sprites in areas of detail. example if we had floorboards we could draw the
` back ground brown and only draw sprites on a few cracks and joins.
return
hide_sprites:
`all sprites are hidden when the spriteres is changed in player_input
`only ones that are needed are shown again when the perspective view is redrawn
`in screendraw:
for d = 10 to 5000
if sprite exist (d) then hide sprite d
next d
return
make_levelmap:
`this only happens before the main loop
`the level map is filled with random data
` each number is a texture
` the level map is used by copy_texture_to_ground_array: to decide which texture to use to fill the ground array
for x=0 to 64
for y=0 to 64
levelmap(x,y)=rnd(3)+1
next x
next y
return
draw_levelmap:
`this is text and lines that are drawn at the top of screen and not part of the perspective view
`draw_levelmap: draws levelmap(64,64) each number represents an image 1 to 4
`these are our tile textures. see put images_in_array: and get_floor_textures:
`it draws a box around the player. the box shows the ground_array(255,255). but may not be aligned properly
for x=0 to 32
for y=0 to 32
num= levelmap(x,y)
text (x*10)+256,y*10,""+str$(num)+""
next x
next y
line (playerx/6.4)-20+256,(playery/6.4)-20,(playerx/6.4)+20+256,(playery/6.4)-20
line (playerx/6.4)-20+256,(playery/6.4)+20,(playerx/6.4)-20+256,(playery/6.4)-20
line (playerx/6.4)-20+256,(playery/6.4)+20,(playerx/6.4)+20+256,(playery/6.4)+20
line (playerx/6.4)+20+256,(playery/6.4)+20,(playerx/6.4)+20+256,(playery/6.4)-20
return
draw_slices:
`this is drawn at the top of screen and not part of the perspective view
`draw_slices: draws the data from depthdata(72,120,40,2)
`it gives a top down view of all the points in the ground plain the player can see
`in the last version you could only look up. now you can see the rotation of the player
box 0,0,256,256,0,0,0,0
for grabx3=0 to 120 step 5
for graby3=0 to 38 step 5
xx1= depthdata(drawangle,grabx3,graby3,1)
yy1= depthdata(drawangle,grabx3,graby3,2)
xx2= depthdata(drawangle,grabx3,graby3,1)
yy2= depthdata(drawangle,grabx3,graby3,2)
line xx1,yy1,xx2+1,yy2+1
next graby3
next grabx3
return
drawall:
`this is drawn at the top of screen and not part of the perspective view
` a top down view of the tiles in the ground plan surronding the player
for grabx=0 to 256 step 10
for graby=0 to 256 step 10
pasteno=ground_array(grabx,graby)
if pasteno=0 then pasteno=10
sprite spritenumber,grabx,graby,pasteno
show sprite spritenumber
size sprite spritenumber,spritesize,spritesize
paste sprite spritenumber,grabx,graby
hide sprite spritenumber
spritenumber=spritenumber+1
next graby
next grabx
return
looks like you've got a framerate over 100. which with the definiton in the image your getting i think is good going.
the floor and ceiling in wolfenstein make more sense to me now
grey square on top of a slightly lighter grey square. job done!!