Code archives/Graphics/Mode7 & live 2d tiles
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
It's great flexible base for any kind of game that needs live tiles (animated oceans, grass etc per frame for example). Also includes a fullblown mode7 ontop which is great to learn from. This uses "slow" pixels and no hardware acc, despite this it reaches well above steady smooth 60 fps on most devices. It's also good project to optimize further and play around with. I see this forum is full of retro gamers so I think this will be appriciated well. So I put this here. Have fun !! Donīt forget to try the different commenting/uncomenting as it changes the experience totally. | |||||
Rem ------------------------------------------ ___ ____ _____ _____ ______ ______ | \ / |/ \| \ | ___| |___ | | \/ || || \| ___| / / |__/\__/|____|\_____/|______/|______| |___| ' Check the source for the important lines to comment / uncomment one at a time. ' ' In 2d mode you can draw, showing the beginning of collision detection of tiles. ' And you may scroll around in this 16MB world, create any size you need. EndRem Global buffer:Int[128*128] Local img2:TPixmap=LoadPixmap(LoadBank("http::s14.postimg.org/xotmro9vh/128x1282.png")) For yy=0 To 127 ; For xx=0 To 127 ; buffer(xx+yy*128) = ReadPixel(img2,xx,yy) ; Next ; Next AddHook FlipHook,irq,Null ; Global fps:Int , fpstotal:Int , msstart:Float , ms:Float = MilliSecs() Global map[4096,4096] ; For yy=0 To 316 ; For xx=0 To 475; map[xx,yy]=Rnd(127) ; Next ; Next For temp=0 To 255 ; map[temp,0]=temp ; Next Global cmap[4096,4096] ; For yy=0 To 316 ; For xx=0 To 475; cmap[xx,yy]=Rnd(15) ; Next ; Next Global wx:Int , wy:Int , cx:Int , c:Int = buffer[0] , cols:Int[16] , s:Int = 2 RestoreData colors ; For temp=0 To 15 ; ReadData cols[temp] ; Next writetomap " ",0,0 writetomap " These letters And symbols are live tiles ",0,1 writetomap " Changing tiles, color of tiles and ",0,2 writetomap " even the atlas at pixel level, each frame ",0,3 writetomap " perfect base for platformers or shootemups ",0,4 writetomap " ",0,5 Global xres:Int = 1024 , yres:Int = 768 , pixels:Int[xres*yres] ' Set resolution here. Local a:Float = 0 , x:Float = 0 , y:Float = 0 , dx:Float = 0 , dy:Float = 0 , speed:Float = 0 Global space_z:Float = 50 , horizon:Int = 20, scale:Float = 1000 , obj_scale:Float = 50 ' Set view and scale here. Global pmap:Int[1024*1024] ; Global img:TPixmap = LoadPixmap(LoadBank("http::static.monstermmorpg.com/images/maps/Meteor-Falls.png")) For y=0 To 1023 ; For x=0 To 1023 ; pmap(x+y*1024) = ReadPixel(img,x,y) ; Next ; Next ' Load png 1024 x 1024 GLGraphics xres,yres,0,60,GRAPHICS_BACKBUFFER | GRAPHICS_DEPTHBUFFER ; glViewport 0,0,xres,yres ' Set 0 for Windowed, 32 for Fullscreen here. glMatrixMode GL_PROJECTION ; glLoadIdentity ; glOrtho 0,xres,yres,0,0,1 ; glPixelZoom 1,-1 ; glRasterPos2i 0,0 '; HideMouse Repeat ' Uncomment this if you want only live tiles, this example uses punctated letters and symbols as tiles. This makes for beutiful dynamic landscapes of gameplay. ' For yy = 0 To 1023 ; For xx = 0 To 1023 ; pmap[yy*1024+xx] = 0 ; Next ; Next ' Comment this if you want only static landscape. alive ; display wx,wy,0,0,1024,1024 ' Render tiles speed = speed + KeyDown(KEY_UP)*0.1-KeyDown(KEY_DOWN)*0.1 ; speed=Max(-5,Min(5,speed)) a = a - KeyDown(KEY_LEFT)+KeyDown(KEY_RIGHT) ; a = a Mod 360 dx = speed * Cos (a) ; dy = speed * Sin (a) ; x :+ dx ; y :+ dy drawplane a,x,y ' For normal 2d tiles, uncomment this. ' readinputs ; for yy = 0 To yres ; For xx = 0 To 1023 ; pixels[yy*xres+xx] = pmap[yy*1024+xx] ; Next ; Next glDrawPixels xres,yres,GL_BGRA,GL_UNSIGNED_BYTE,pixels Delay 1 ; Flip 1 Until KeyHit(KEY_ESCAPE) Or AppTerminate() End Function drawplane(a:Float,cx:Float,cy:Float) Local sx:Int , sy:Int , d:Float , hs:Float , maskx:Int = 1023 , masky:Int = 1023 Local dx:Float , dy:Float , spx:Float,spy:Float For sy = 0 Until yres-1 Step 2 d = space_z*scale / Float(sy + horizon) ; hs = d / scale ; dx = -Sin(a) * hs ; dy = Cos(a) * hs spx = cx + d*Cos(a) - Float(xres) / 2 * dx ; spy = cy + d*Sin(a) - Float(xres) / 2 * dy For sx = 0 Until xres-1 ; pixels[sx+sy*xres] = pmap[(Int(spx) & maskx) + ( (Int(spy) & masky)*1024)] ; spx :+ dx ; spy :+ dy ; Next Next End Function Function alive() For temp=1 To 16 ; buffer[Int(Rand(0,15))+Int((Rand(0,15))*128)]=$ffffffff * Int(Rand(0,1)) ; Next cx=(cx+1) Mod 128 ; For tempy=0 To 15 ; For temp=0 To 15+32 ; buffer[16+temp+((0+tempy)*128)]=buffer[0+temp+cx+(16+tempy)*128] ; Next ; Next ; For temp=1 To 1600 ; cmap[Rnd(400),Rnd(250)]=Rnd(16) ; Next End Function Function display(wx,wy,ofx=0,ofy=0,sx=640,sy=400) scrx = wx & 15 ; scry = wy & 15 ; mapx = wx Shr 4 ; mapy = wy Shr 4 cnty = 0 ; For y = mapy To mapy+(sy Shr 4+1) cntx = 0 ; For x = mapx To mapx+(sx Shr 4+1) tilex = map(x,y) & 15 ; tiley = map(x,y) Shr 4 colour = cols(cmap(x,y)) ; xx = cntx - scrx + ofx ; yy=cnty - scry + ofy For ty = 0 To 7 ; For tx = 0 To 7 If (xx+tx+tx >= ofx) And (yy+ty+ty >= ofy) And (xx+tx+tx < ofx+sx) And (yy+ty+ty < ofy+sy).. ' Mind the steps And buffer[tilex Shl 3 + tx + (tiley Shl 3 + ty)*128] <> c Then pmap[xx+tx+tx+(yy+ty+ty)*1024] = colour Next ; Next cntx = cntx+16 ; Next cnty = cnty+16 ; Next End Function Function readinputs() wx=wx-s*KeyDown(KEY_LEFT)+s*KeyDown(KEY_RIGHT) ; wy=wy-s*KeyDown(KEY_UP)+s*KeyDown(KEY_DOWN) ; wx=Max(0,Min(10000,wx)) ; wy=Max(0,Min(10000,wy)) mx = MouseX() ; my = MouseY() ; xxx = (wx+mx) Sar 4 ; yyy = (wy+my) Sar 4 ; If MouseDown(1) Then map(xxx,yyy) = 42 ; cmap(xxx,yyy) = 7 End Function Function writetomap(t$,x,y) For tempx = 0 To Len(t$)-1 ; temp = Asc(Mid$(t$,1+tempx,1)) ; map[tempx+x,y] = temp ; cmap[tempx+x,y] = 14 ; Next End Function Function irq:Object(id,data:Object,context:Object) Return data End Function #colors DefData $000000,$FFFFFF,$68372B,$70A4B2,$6F3D86,$588D43,$352879,$B8C76F,$6F4F25,$433900,$9A6759,$444444,$6C6C6C,$9AD284,$6C5EB5,$959595 |
Comments
| ||
Great, thanks. |
| ||
Very nice! Runs great here. Two minor quibbles: 1) Doesn't work with Brucey's BMX-NG as it's not SuperStrict-compliant. Also uses () brackets for array access, which seems to be allowed in standard Max, but arguably shouldn't be... again, this fails in BMX-NG. 2) The demo defaults to using the "live tiles", and I just thought it was a graphical glitch at first! Perhaps it could use a toggle to turn live tiles on? (Would leave them off by default.) Really nice results, though. |
| ||
Thanks. Iīm not into superstrict at the moment, does that help to optimize the inner workings or is it for tidying definitions etc? My thought is.. it is probably possible to do easly for someone who know it, I just havn't ever used superstrict yet. Yes I wanted a very hybrid demo, showing alot of things without pressing keys, it looks glitchy but it is not. I wanted some choices inside the comments instead. |
| ||
Let's try it again to show of that "Aliveness" abit better. I keep the original becuase this is a light version of it. This upcoming one also shows of Bmax's weakneses in CPU usage when combining huge Inner loops and conditions, it makes it very slow. That's also why I skipped every other pixel in the 1st one. Here you go. Live tiles, abit more sensible demo. But the above code is the real workhorse which brings all this, so donīt use this. This is just a demo. Global buffer:Int[256*256] ; Local img2:TPixmap=LoadPixmap(LoadBank("http::www.foxhack.net/files/blog/2008/01-09-charadata.png")) ' Load a 256x256 Atlas with 8x8 tiles For yy=0 To 255 ; For xx=0 To 255 ; buffer(xx+yy*256) = ReadPixel(img2,xx,yy) ; Next ; Next Global map[4096,4096] , wx:Int , wy:Int , cx:Int , c:Int = buffer[0] , s:Int = 2 , xres:Int = 1024 , yres:Int = 768 , pixels:Int[xres*yres] Local a:Float = 0 , x:Float = 0 , y:Float = 0 , dx:Float = 0 , dy:Float = 0 , speed:Float = 0 Global space_z:Float = 50 , horizon:Int = 20, scale:Float = 1000 , obj_scale:Float = 50 , pmap:Int[1024*1024] ' Fill world with atlas 1:1 side by side For worldy=0 To 4095 Step 32 ; For worldx=0 To 4095 Step 32 ; For temp2=0 To 31 ; For temp=0 To 31 ; map(temp+worldx,temp2+worldy)=temp+temp2*32 ; Next ; Next ; Next ; Next GLGraphics xres,yres,0,60,GRAPHICS_BACKBUFFER | GRAPHICS_DEPTHBUFFER ; glViewport 0,0,xres,yres glMatrixMode GL_PROJECTION ; glLoadIdentity ; glOrtho 0,xres,yres,0,0,1 ; glPixelZoom 1,-1 ; glRasterPos2i 0,0 Repeat For yy = 0 To 1023 ; For xx = 0 To 1023 ; pmap[yy*1024+xx] = 0 ; Next ; Next display wx,wy,0,0,1024,1024 speed = speed + KeyDown(KEY_UP)*0.1-KeyDown(KEY_DOWN)*0.1 ; speed=Max(-5,Min(5,speed)) a = a - KeyDown(KEY_LEFT)+KeyDown(KEY_RIGHT) ; a = a Mod 360 dx = speed * Cos (a) ; dy = speed * Sin (a) ; x :+ dx ; y :+ dy drawplane a,x,y alive 'readinputs ; For yy = 0 To yres ; For xx = 0 To 1023 ; pixels[yy*xres+xx] = pmap[yy*1024+xx] ; Next ; Next ' Show 2D glDrawPixels xres,yres,GL_BGRA,GL_UNSIGNED_BYTE,pixels Delay 1 ; Flip 1 Until KeyHit(KEY_ESCAPE) Or AppTerminate() End Function readinputs() wx=wx-s*KeyDown(KEY_LEFT)+s*KeyDown(KEY_RIGHT) ; wy=wy-s*KeyDown(KEY_UP)+s*KeyDown(KEY_DOWN) ; wx=Max(0,Min(10000,wx)) ; wy=Max(0,Min(10000,wy)) mx = MouseX() ; my = MouseY() ; xxx = (wx+mx) Sar 3 ; yyy = (wy+my) Sar 3; If MouseDown(1) Then map(xxx,yyy) = 42 End Function Function alive() For temp=1 To 16 ; buffer[Int(Rand(0,15))+Int((Rand(0,15))*128)]=$ffffffff * Int(Rand(0,1)) ; Next cx=cx+1 Mod 128 ; For tempy=0 To 15 ; For temp=0 To 15+32 ; buffer[16+temp+((0+tempy)*128)]=buffer[0+temp+cx+(16+tempy)*128] ; Next ; Next End Function Function drawplane(a:Float,cx:Float,cy:Float) ' This might need optimzation too but it has not as intens loops so actually it does not need at all as much as display() does. Local sx:Int , sy:Int , d:Float , hs:Float , maskx:Int = 1023 , masky:Int = 1023 Local dx:Float , dy:Float , spx:Float,spy:Float For sy = 0 Until yres-1 Step 2 d = space_z*scale / Float(sy + horizon) ; hs = d / scale ; dx = -Sin(a) * hs ; dy = Cos(a) * hs spx = cx + d*Cos(a) - Float(xres) / 2 * dx ; spy = cy + d*Sin(a) - Float(xres) / 2 * dy For sx = 0 Until xres-1 ; pixels[sx+sy*xres] = pmap[(Int(spx) & maskx) + ( (Int(spy) & masky)*1024)] ; spx :+ dx ; spy :+ dy ; Next Next End Function Function display(wx,wy,ofx=0,ofy=0,sx=640,sy=400) ' Here's where most optimization is needed (as it is it can't keep up with steady 60 fps on average machines, every teeny fraction of Bmax knowledge should be put in here. Unrolling helps, less conditions helps. scrx = wx & 7 ; scry = wy & 7 ; mapx = wx Shr 3 ; mapy = wy Shr 3 cnty = 0 ; For y = mapy To mapy+(sy Shr 3+1) cntx = 0 ; For x = mapx To mapx+(sx Shr 3+1) tilex = map(x,y) & 31 ; tiley = map(x,y) Shr 5 ' 32 tiles per line in atlas xx = cntx - scrx + ofx ; yy=cnty - scry + ofy For ty = 0 To 7 ; For tx = 0 To 7 If xx+tx >= ofx And yy+ty >= ofy And xx+tx < ofx+sx And yy+ty < ofy+sy .. Then pmap[xx+tx+(yy+ty)Shl 10] = buffer[tilex Shl 3 + tx + (tiley Shl 3 + ty) Shl 8] Next ; Next cntx = cntx+8 ; Next cnty = cnty+8 ; Next End Function |
| ||
This should help a little: (I'm using the code from the first post, not the last one...) Sorry if I idented your code - it was easier for me to understand what was going on ;) What I did was to precompute as much as I could in both routines *outside* of the loops. For example, on "display" you were computing yy+ty+ty 64 times * 3 * how many times the for x / for y outer loops runs. I don't know how much of a toll this means nowadays, but I know every little bit helps, so... :) |
| ||
Sorry if I idented your code - it was easier for me to understand what was going on And for most of everyone else too, I'd imagine. Thanks. |
| ||
@Casaber Your code is ingenious and superb. But you really need to use super strict and also learn to indent you code and separate it so it is readable :) Here is the corrected code for the rest of us: superstrict Global buffer:Int[256*256] Local img2:TPixmap=LoadPixmap(LoadBank("http::www.foxhack.net/files/blog/2008/01-09-charadata.png")) ' Load a 256x256 Atlas with 8x8 tiles local xx:int local yy:int For yy = 0 To 255 For xx = 0 To 255 buffer[xx+yy*256] = ReadPixel(img2,xx,yy) Next Next Global map:int[4096,4096]; global wx:Int global wy:Int global cx:Int global c:Int = buffer[0] global s:Int = 2 global xres:Int = 1024 global yres:Int = 768 global pixels:Int[xres*yres] Local a:Float = 0 local x:Float = 0 local y:Float = 0 local dx:Float = 0 local dy:Float = 0 local speed:Float = 0 Global space_z:Float = 50 global horizon:Int = 20 global scale:Float = 1000 global obj_scale:Float = 50 global pmap:Int[1024*1024] ' Fill world with atlas 1:1 side by side local worldx:int local worldy:int local temp2:int local temp:int For worldy = 0 To 4095 Step 32 For worldx = 0 To 4095 Step 32 For temp2 = 0 To 31 For temp = 0 To 31 map[temp+worldx, temp2+worldy] = temp+temp2*32 Next Next Next Next GLGraphics xres,yres,0,60,GRAPHICS_BACKBUFFER | GRAPHICS_DEPTHBUFFER glViewport 0,0,xres,yres glMatrixMode GL_PROJECTION glLoadIdentity glOrtho 0,xres,yres,0,0,1 glPixelZoom 1,-1 glRasterPos2i 0,0 Repeat display wx,wy,0,0,1024,1024 speed = speed + KeyDown(KEY_UP)*0.1-KeyDown(KEY_DOWN)*0.1 speed=Max(-5,Min(5,speed)) a = a - KeyDown(KEY_LEFT)+KeyDown(KEY_RIGHT) a = a Mod 360 dx = speed * Cos (a) dy = speed * Sin (a) x :+ dx y :+ dy drawplane a,x,y alive 'readinputs ; For yy = 0 To yres ; For xx = 0 To 1023 ; pixels[yy*xres+xx] = pmap[yy*1024+xx] ; Next ; Next ' Show 2D glDrawPixels xres,yres,GL_BGRA,GL_UNSIGNED_BYTE,pixels Delay 1 Flip 1 Until KeyHit(KEY_ESCAPE) Or AppTerminate() End Function readinputs() wx=wx-s*KeyDown(KEY_LEFT)+s*KeyDown(KEY_RIGHT) wy=wy-s*KeyDown(KEY_UP)+s*KeyDown(KEY_DOWN) wx=Max(0,Min(10000,wx)) wy=Max(0,Min(10000,wy)) local mx:int = MouseX() local my:int = MouseY() local xxx:int = (wx+mx) Sar 3 local yyy:int = (wy+my) Sar 3 If MouseDown(1) Then map[xxx,yyy] = 42 End Function Function alive() local temp:int local tempy:int For temp = 1 To 16 buffer[Int(Rand(0,15))+Int((Rand(0,15))*128)]=$ffffffff * Int(Rand(0,1)) Next cx=cx+1 Mod 128 For tempy = 0 To 15 For temp = 0 To 15+32 buffer[16+temp+((0+tempy)*128)] = buffer[0+temp+cx+(16+tempy)*128] Next Next End Function Function drawplane(a:Float,cx:Float,cy:Float) ' This might need optimzation too but it has not as intens loops so actually it does not need at all as much as display() does. Local sx:Int local sy:Int local d:Float local hs:Float local maskx:Int = 1023 local masky:Int = 1023 Local dx:Float local dy:Float local spx:Float local spy:Float For sy = 0 Until yres-1 Step 2 d = space_z*scale / Float(sy + horizon) hs = d / scale dx = -Sin(a) * hs dy = Cos(a) * hs spx = cx + d*Cos(a) - Float(xres) / 2 * dx spy = cy + d*Sin(a) - Float(xres) / 2 * dy For sx = 0 Until xres-1 pixels[sx+sy*xres] = pmap[(Int(spx) & maskx) + ( (Int(spy) & masky)*1024)] spx :+ dx spy :+ dy Next Next End Function Function display(wx:int, wy:int, ofx:float = 0, ofy:float = 0, sx:int = 640, sy:int = 400) ' Here's where most optimization is needed (as it is it can't keep up with steady 60 fps on average machines, every teeny fraction of Bmax knowledge should be put in here. Unrolling helps, less conditions helps. local scrx:int local scry:int local mapx:int local mapy:int scrx = wx & 7 scry = wy & 7 mapx = wx Shr 3 mapy = wy Shr 3 local cnty:int = 0 local cntx:int local ty:int local tx:int local x:int local y:int local tilex:int local tiley:int local xx:int local yy:int For y = mapy To mapy+(sy Shr 3+1) cntx = 0 For x = mapx To mapx+(sx Shr 3+1) tilex = map[x,y] & 31 tiley = map[x,y] Shr 5 ' 32 tiles per line in atlas xx = cntx - scrx + ofx yy=cnty - scry + ofy For ty = 0 To 7 For tx = 0 To 7 if xx+tx >= ofx And yy+ty >= ofy And xx+tx < ofx+sx And yy+ty < ofy+sy Then pmap[xx+tx+(yy+ty)Shl 10] = buffer[tilex Shl 3 + tx + (tiley Shl 3 + ty) Shl 8] end if Next Next cntx = cntx+8 Next cnty = cnty+8 Next End Function |
| ||
I got response here, well thanks. Glad you like it, I thought this will help lot of coders, I guess it will help mostly those who understand. I'lll try to clean things up but not like that, not with pure layout design, I will clean up the concepts. That's more important. It's a bit messy but this IS a work in progress okay. I should have mentioned that. This is not finished. Well let me tell you about my style then, many people seem to think its a misstake. It's not. It has a long story. I code in meaningful chunks, with deep meaning behind how they got there, and how I choose what to put where. Sometimes sloppy position ya but that's.. okay. Usually I tidy things up at the end. Or not, if I'm in a hurry and want or need to share something quickly. I usually tell them that it's personal, I guess I forgot here. I'm working with ppl where i need to take care about things like eye movements and the amount you have to use a touch, pen or mouse for instance, you donīt want to move about alot. There's alot of meaningfdul reasons for that I wonīt go on that but, also I use screen real estate other reasons, one of them is to have a better glance and overview and a better feeling of my work when I'm working. Which is actually the backbone for using you know, indents (which basically is wasteful vertical way to do what Iīm trying to do. I might share code sometimes with you. and if I do, you will get what I have. Long long time ago I used vertical indents etc ALOT, and had very strict layout for many years before I knew how terrible it is. The goal , the INTENT, is a good one. But how it is reached, is not. I guess recommended those techniques 15 years ago. Now I am not convinced that it is a good idea in any common case. Just beacuse it's used everywhere does not mean it is good. If you do it every day, then of course your eyes are used to it, and you are quick about it .And you want it that way. So ya, I understand your feelings about that. If anyone is interested in the details what Iīm doing we could talk some day. |
| ||
Guess you missed the whole part about optimizations I did? I really don't care about your formatting, or why you do it like that - I wasn't criticizing or anything - as I said - and that's all there is to it - FOR ME, it's better that way to understand it. The problems others may have with the formatting is specially aggravated since you posted in the code archive section - which is exactly to have code to show others how things are made. I'd still say that's ok - but then you come and say that this is *still* a work in progress... so the code shouldn't be in the archives? (I'm really asking, I'm not an admin here or anything - at all.) Anyway, sorry if my formatting caused all this trouble - keep coding and doing the cool work you're doing! :) |
| ||
I forgot about your optimization Slotman, sorry, that was a nice one. Excellent move. I was not talking to you personally, just general announcement so no worries. |
| ||
I was thinking, ya.. it took ALONG time to me to decide, if it was worth uplaoding to the archives. archives or no archives.. it's like a painting you know.. when is it ready? It never is. you can ALWAYS dab that extra slab of color onto it, you know? Was I wrong this time? |
| ||
I think some ppl goe a kick out of it, if even only single person liked it, it was worth it. It's small, it's very tinker-friendly. I think I let this stay up. |
| ||
I think you're right about archives should have a more.. carefully "outwards" designed code. ya. I think i did the decision too fast. But i knew if i didnt do it know it would never happened. and it would be stuck in a thread wo ever getting seen by those who want it. |
| ||
And most of all, a big thanks goes for the more public version made here. Very nice. |
| ||
Nothing wrong with posting working code in the Code Archives! I do think it's worth taking into account the comments about code formatting and strictness. Besides, you can always edit and update your Code Archives entries anyway -- there's no need to leave it static as you make improvements. |
| ||
Is there a Blitz3D version of this? I would REALLY like to try it out! :( ~GF |
| ||
I donīt have access to PC now, but it I think it might be nice to hear that this actually was B3D code originally of mine which I created on an EEE 701 (weak little but cute practical netbook). Where it run 60fps on. I converted this nto Bmax/opengl and then added MODE7 ontop. I don't like to promise things that I can't keep, but I will try look for the original and then add the changes I've made. I feel I want to do so many things now, I would love to add all the optimziations everyone's made here with my last one in the thread and make a single one. And do a "proper" layout and conceptually easy to read code. But I'm short of time right but I would really like to do that. The fact is that I'm already burned out so don't hold your breath, but I want to say B3D has what it takes to do the same. Absolutely, WRITEPIXELFAST will give 50-100% of the speed here. About SUPERSTRICT I will try learn that whenever I can, I have my other foot now in Monkey 2 but I really enjoy BMax. I hope strict does not force you using alot of odd symbols that brings nothing to the table. If so I will use it for sure. Same goes with Monkey2 I guess. |
| ||
It would be AWESOME to be able to use this code in B3D for like a tile map loader and a small demo of moving a character in 8 directions like in Chrono Trigger with this thing. That would be freakin' SICK! (In a good way! ) :) ~GF |
| ||
@Casaber I took the display code and further optimised it for you. i then optimised the optimisations and came up with this:Function display(wx:int, wy:int, ofx:int = 0, ofy:int = 0, sx:int = 640, sy:int = 400) ' Here's where most optimization is needed (as it is it can't keep up with steady 60 fps on average machines, every teeny fraction of Bmax knowledge should be put in here. Unrolling helps, less conditions helps. local scrx:int local scry:int local mapx:int local mapy:int scrx = wx & 7 scry = wy & 7 mapx = wx Shr 3 mapy = wy Shr 3 local cnty:int = 0 local cntx:int local ty:int local tx:int local x:int local y:int local tilex:int local tiley:int local xx:int local yy:int local mapysy:int = mapy+(sy Shr 3+1) local mapxsx:int = mapx+(sx Shr 3+1) local yyty:int local tileyshl:int local yytyshl:int local tileyty:int local xxtx:int local ofxsx:int local tilexshl:int local tilexShltileyty:int local xxtxyy:int ofxsx = ofx+sx For y = mapy To mapysy yy = cnty - scry + ofy cntx = 0 For x = mapx To mapxsx tilex = map[x,y] & 31 tiley = map[x,y] Shr 5 ' 32 tiles per line in atlas tileyshl = tiley Shl 3 tilexshl = tilex shl 3 xx = cntx - scrx + ofx For ty = 0 To 7 yyty = yy+ty if yyty >= ofy And yyty < ofy+sy Then yytyshl = yyty Shl 10 tileyty = (tileyShl + ty) Shl 8 xxtx = xx xxtxyy = xxtx + yytyshl if xxtx >= ofx And xxtx < ofxsx Then tilexShltileyty = tilexShl + tileyty pmap[ xxtxyy ] = buffer[tilexShltileyty] xxtx :+ 1 if xxtx < ofxsx Then tilexShltileyty :+ 1 xxtxyy :+ 1 pmap[ xxtxyy ] = buffer[tilexShltileyty] xxtx :+ 1 if xxtx < ofxsx Then tilexShltileyty :+ 1 xxtxyy :+ 1 pmap[ xxtxyy ] = buffer[tilexShltileyty] xxtx :+ 1 if xxtx < ofxsx Then tilexShltileyty :+ 1 xxtxyy :+ 1 pmap[ xxtxyy ] = buffer[tilexShltileyty] xxtx :+ 1 if xxtx < ofxsx Then tilexShltileyty :+ 1 xxtxyy :+ 1 pmap[ xxtxyy ] = buffer[tilexShltileyty] xxtx :+ 1 if xxtx < ofxsx Then tilexShltileyty :+ 1 xxtxyy :+ 1 pmap[ xxtxyy ] = buffer[tilexShltileyty] xxtx :+ 1 if xxtx < ofxsx Then tilexShltileyty :+ 1 xxtxyy :+ 1 pmap[ xxtxyy ] = buffer[tilexShltileyty] xxtx :+ 1 if xxtx < ofxsx Then tilexShltileyty :+ 1 xxtxyy :+ 1 pmap[ xxtxyy ] = buffer[tilexShltileyty] end if end if end if end if end if end if end if end if end if Next cntx = cntx+8 Next cnty = cnty+8 Next End Function in essence it is about removing the conditions and one set of loops plus pre calculating as much as possible. It sort of shaves about 10-20% speed of your optimised version |
Code Archives Forum